LMMS
Loading...
Searching...
No Matches
ImageBaseWidgets.cpp
Go to the documentation of this file.
1/*
2 * DISTRHO Plugin Framework (DPF)
3 * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any purpose with
6 * or without fee is hereby granted, provided that the above copyright notice and this
7 * permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "../ImageBaseWidgets.hpp"
18#include "../Color.hpp"
19
20START_NAMESPACE_DGL
21
22// --------------------------------------------------------------------------------------------------------------------
23
24template <class ImageType>
25ImageBaseAboutWindow<ImageType>::ImageBaseAboutWindow(Window& transientParentWindow, const ImageType& image)
26 : StandaloneWindow(transientParentWindow.getApp(), transientParentWindow),
27 img(image)
28{
29 setResizable(false);
30 setTitle("About");
31
32 if (image.isValid())
33 {
34 setSize(image.getSize());
35 setGeometryConstraints(image.getWidth(), image.getHeight(), true, true);
36 }
37
38 done();
39}
40
41template <class ImageType>
42ImageBaseAboutWindow<ImageType>::ImageBaseAboutWindow(TopLevelWidget* const topLevelWidget, const ImageType& image)
43 : StandaloneWindow(topLevelWidget->getApp(), topLevelWidget->getWindow()),
44 img(image)
45{
46 setResizable(false);
47 setTitle("About");
48
49 if (image.isValid())
50 {
51 setSize(image.getSize());
52 setGeometryConstraints(image.getWidth(), image.getHeight(), true, true);
53 }
54
55 done();
56}
57
58template <class ImageType>
59void ImageBaseAboutWindow<ImageType>::setImage(const ImageType& image)
60{
61 if (img == image)
62 return;
63
64 img = image;
65
66 if (image.isInvalid())
67 return;
68
69 setSize(image.getSize());
70 setGeometryConstraints(image.getWidth(), image.getHeight(), true, true);
71}
72
73template <class ImageType>
74void ImageBaseAboutWindow<ImageType>::onDisplay()
75{
76 img.draw(getGraphicsContext());
77}
78
79template <class ImageType>
80bool ImageBaseAboutWindow<ImageType>::onKeyboard(const KeyboardEvent& ev)
81{
82 if (ev.press && ev.key == kKeyEscape)
83 {
84 close();
85 return true;
86 }
87
88 return false;
89}
90
91template <class ImageType>
92bool ImageBaseAboutWindow<ImageType>::onMouse(const MouseEvent& ev)
93{
94 if (ev.press)
95 {
96 close();
97 return true;
98 }
99
100 return false;
101}
102
103// --------------------------------------------------------------------------------------------------------------------
104
105template <class ImageType>
106struct ImageBaseButton<ImageType>::PrivateData : public ButtonEventHandler::Callback {
107 ImageBaseButton<ImageType>::Callback* callback;
108 ImageType imageNormal;
109 ImageType imageHover;
110 ImageType imageDown;
111
112 PrivateData(const ImageType& normal, const ImageType& hover, const ImageType& down)
113 : callback(nullptr),
115 imageHover(hover),
116 imageDown(down) {}
117
118 void buttonClicked(SubWidget* widget, int button) override
119 {
120 if (callback != nullptr)
121 if (ImageBaseButton* const imageButton = dynamic_cast<ImageBaseButton*>(widget))
122 callback->imageButtonClicked(imageButton, button);
123 }
124
126};
127
128// --------------------------------------------------------------------------------------------------------------------
129
130template <class ImageType>
131ImageBaseButton<ImageType>::ImageBaseButton(Widget* const parentWidget, const ImageType& image)
132 : SubWidget(parentWidget),
133 ButtonEventHandler(this),
134 pData(new PrivateData(image, image, image))
135{
136 ButtonEventHandler::setCallback(pData);
137 setSize(image.getSize());
138}
139
140template <class ImageType>
141ImageBaseButton<ImageType>::ImageBaseButton(Widget* const parentWidget, const ImageType& imageNormal, const ImageType& imageDown)
142 : SubWidget(parentWidget),
143 ButtonEventHandler(this),
144 pData(new PrivateData(imageNormal, imageNormal, imageDown))
145{
146 DISTRHO_SAFE_ASSERT(imageNormal.getSize() == imageDown.getSize());
147
148 ButtonEventHandler::setCallback(pData);
149 setSize(imageNormal.getSize());
150}
151
152template <class ImageType>
153ImageBaseButton<ImageType>::ImageBaseButton(Widget* const parentWidget, const ImageType& imageNormal, const ImageType& imageHover, const ImageType& imageDown)
154 : SubWidget(parentWidget),
155 ButtonEventHandler(this),
156 pData(new PrivateData(imageNormal, imageHover, imageDown))
157{
158 DISTRHO_SAFE_ASSERT(imageNormal.getSize() == imageHover.getSize() && imageHover.getSize() == imageDown.getSize());
159
160 ButtonEventHandler::setCallback(pData);
161 setSize(imageNormal.getSize());
162}
163
164template <class ImageType>
165ImageBaseButton<ImageType>::~ImageBaseButton()
166{
167 delete pData;
168}
169
170template <class ImageType>
171void ImageBaseButton<ImageType>::setCallback(Callback* callback) noexcept
172{
173 pData->callback = callback;
174}
175
176template <class ImageType>
177void ImageBaseButton<ImageType>::onDisplay()
178{
179 const GraphicsContext& context(getGraphicsContext());
180
181 const State state = ButtonEventHandler::getState();
182
183 if (state & kButtonStateActive)
184 pData->imageDown.draw(context);
185 else if (state & kButtonStateHover)
186 pData->imageHover.draw(context);
187 else
188 pData->imageNormal.draw(context);
189}
190
191template <class ImageType>
192bool ImageBaseButton<ImageType>::onMouse(const MouseEvent& ev)
193{
194 if (SubWidget::onMouse(ev))
195 return true;
196 return ButtonEventHandler::mouseEvent(ev);
197}
198
199template <class ImageType>
200bool ImageBaseButton<ImageType>::onMotion(const MotionEvent& ev)
201{
202 if (SubWidget::onMotion(ev))
203 return true;
204 return ButtonEventHandler::motionEvent(ev);
205}
206
207// --------------------------------------------------------------------------------------------------------------------
208
209template <class ImageType>
210struct ImageBaseKnob<ImageType>::PrivateData : public KnobEventHandler::Callback {
211 ImageBaseKnob<ImageType>::Callback* callback;
212 ImageType image;
213
215
222
223 union {
226 };
227
228 explicit PrivateData(const ImageType& img)
229 : callback(nullptr),
230 image(img),
231 rotationAngle(0),
233 isImgVertical(img.getHeight() > img.getWidth()),
234 imgLayerWidth(isImgVertical ? img.getWidth() : img.getHeight()),
236 imgLayerCount(isImgVertical ? img.getHeight()/imgLayerHeight : img.getWidth()/imgLayerWidth),
238 {
239 init();
240 }
241
242 explicit PrivateData(PrivateData* const other)
243 : callback(other->callback),
244 image(other->image),
252 {
253 init();
254 }
255
256 void assignFrom(PrivateData* const other)
257 {
258 cleanup();
259 image = other->image;
261 callback = other->callback;
267 isReady = false;
268 init();
269 }
270
272 {
273 cleanup();
274 }
275
276 void knobDragStarted(SubWidget* const widget) override
277 {
278 if (callback != nullptr)
279 if (ImageBaseKnob* const imageKnob = dynamic_cast<ImageBaseKnob*>(widget))
280 callback->imageKnobDragStarted(imageKnob);
281 }
282
283 void knobDragFinished(SubWidget* const widget) override
284 {
285 if (callback != nullptr)
286 if (ImageBaseKnob* const imageKnob = dynamic_cast<ImageBaseKnob*>(widget))
287 callback->imageKnobDragFinished(imageKnob);
288 }
289
290 void knobValueChanged(SubWidget* const widget, const float value) override
291 {
292 if (rotationAngle == 0 || alwaysRepaint)
293 isReady = false;
294
295 if (callback != nullptr)
296 if (ImageBaseKnob* const imageKnob = dynamic_cast<ImageBaseKnob*>(widget))
297 callback->imageKnobValueChanged(imageKnob, value);
298 }
299
300 // implemented independently per graphics backend
301 void init();
302 void cleanup();
303
305};
306
307// --------------------------------------------------------------------------------------------------------------------
308
309template <class ImageType>
310ImageBaseKnob<ImageType>::ImageBaseKnob(Widget* const parentWidget,
311 const ImageType& image,
312 const Orientation orientation) noexcept
313 : SubWidget(parentWidget),
314 KnobEventHandler(this),
315 pData(new PrivateData(image))
316{
317 KnobEventHandler::setCallback(pData);
318 setOrientation(orientation);
319 setSize(pData->imgLayerWidth, pData->imgLayerHeight);
320}
321
322template <class ImageType>
323ImageBaseKnob<ImageType>::ImageBaseKnob(const ImageBaseKnob<ImageType>& imageKnob)
324 : SubWidget(imageKnob.getParentWidget()),
325 KnobEventHandler(this, imageKnob),
326 pData(new PrivateData(imageKnob.pData))
327{
328 KnobEventHandler::setCallback(pData);
329 setOrientation(imageKnob.getOrientation());
330 setSize(pData->imgLayerWidth, pData->imgLayerHeight);
331}
332
333template <class ImageType>
334ImageBaseKnob<ImageType>& ImageBaseKnob<ImageType>::operator=(const ImageBaseKnob<ImageType>& imageKnob)
335{
336 KnobEventHandler::operator=(imageKnob);
337 pData->assignFrom(imageKnob.pData);
338 setSize(pData->imgLayerWidth, pData->imgLayerHeight);
339 return *this;
340}
341
342template <class ImageType>
343ImageBaseKnob<ImageType>::~ImageBaseKnob()
344{
345 delete pData;
346}
347
348template <class ImageType>
349void ImageBaseKnob<ImageType>::setCallback(Callback* callback) noexcept
350{
351 pData->callback = callback;
352}
353
354template <class ImageType>
355void ImageBaseKnob<ImageType>::setImageLayerCount(uint count) noexcept
356{
358
359 pData->imgLayerCount = count;
360
361 if (pData->isImgVertical)
362 pData->imgLayerHeight = pData->image.getHeight()/count;
363 else
364 pData->imgLayerWidth = pData->image.getWidth()/count;
365
366 setSize(pData->imgLayerWidth, pData->imgLayerHeight);
367}
368
369template <class ImageType>
370void ImageBaseKnob<ImageType>::setRotationAngle(int angle)
371{
372 if (pData->rotationAngle == angle)
373 return;
374
375 pData->rotationAngle = angle;
376 pData->isReady = false;
377}
378
379template <class ImageType>
380bool ImageBaseKnob<ImageType>::setValue(float value, bool sendCallback) noexcept
381{
382 if (KnobEventHandler::setValue(value, sendCallback))
383 {
384 if (pData->rotationAngle == 0 || pData->alwaysRepaint)
385 pData->isReady = false;
386
387 return true;
388 }
389
390 return false;
391}
392
393template <class ImageType>
394bool ImageBaseKnob<ImageType>::onMouse(const MouseEvent& ev)
395{
396 if (SubWidget::onMouse(ev))
397 return true;
398 return KnobEventHandler::mouseEvent(ev);
399}
400
401template <class ImageType>
402bool ImageBaseKnob<ImageType>::onMotion(const MotionEvent& ev)
403{
404 if (SubWidget::onMotion(ev))
405 return true;
406 return KnobEventHandler::motionEvent(ev);
407}
408
409template <class ImageType>
410bool ImageBaseKnob<ImageType>::onScroll(const ScrollEvent& ev)
411{
412 if (SubWidget::onScroll(ev))
413 return true;
414 return KnobEventHandler::scrollEvent(ev);
415}
416
417// --------------------------------------------------------------------------------------------------------------------
418
419template <class ImageType>
420struct ImageBaseSlider<ImageType>::PrivateData {
421 ImageType image;
422 float minimum;
423 float maximum;
424 float step;
425 float value;
426 float valueDef;
427 float valueTmp;
429
433 double startedX;
434 double startedY;
435
436 Callback* callback;
437
438 Point<int> startPos;
439 Point<int> endPos;
441
442 PrivateData(const ImageType& img)
443 : image(img),
444 minimum(0.0f),
445 maximum(1.0f),
446 step(0.0f),
447 value(0.5f),
454 startedX(0.0),
455 startedY(0.0),
457 startPos(),
458 endPos(),
459 sliderArea() {}
460
462 {
463 if (startPos.getY() == endPos.getY())
464 {
465 // horizontal
467 startPos.getY(),
468 endPos.getX() + static_cast<int>(image.getWidth()) - startPos.getX(),
469 static_cast<int>(image.getHeight()));
470 }
471 else
472 {
473 // vertical
475 startPos.getY(),
476 static_cast<int>(image.getWidth()),
477 endPos.getY() + static_cast<int>(image.getHeight()) - startPos.getY());
478 }
479 }
480
482};
483
484// --------------------------------------------------------------------------------------------------------------------
485
486template <class ImageType>
487ImageBaseSlider<ImageType>::ImageBaseSlider(Widget* const parentWidget, const ImageType& image) noexcept
488 : SubWidget(parentWidget),
489 pData(new PrivateData(image))
490{
491 setNeedsFullViewportDrawing();
492}
493
494template <class ImageType>
495ImageBaseSlider<ImageType>::~ImageBaseSlider()
496{
497 delete pData;
498}
499
500template <class ImageType>
501float ImageBaseSlider<ImageType>::getValue() const noexcept
502{
503 return pData->value;
504}
505
506template <class ImageType>
507void ImageBaseSlider<ImageType>::setValue(float value, bool sendCallback) noexcept
508{
509 if (! pData->valueIsSet)
510 pData->valueIsSet = true;
511
512 if (d_isEqual(pData->value, value))
513 return;
514
515 pData->value = value;
516
517 if (d_isZero(pData->step))
518 pData->valueTmp = value;
519
520 repaint();
521
522 if (sendCallback && pData->callback != nullptr)
523 {
524 try {
525 pData->callback->imageSliderValueChanged(this, pData->value);
526 } DISTRHO_SAFE_EXCEPTION("ImageBaseSlider::setValue");
527 }
528}
529
530template <class ImageType>
531void ImageBaseSlider<ImageType>::setStartPos(const Point<int>& startPos) noexcept
532{
533 pData->startPos = startPos;
534 pData->recheckArea();
535}
536
537template <class ImageType>
538void ImageBaseSlider<ImageType>::setStartPos(int x, int y) noexcept
539{
540 setStartPos(Point<int>(x, y));
541}
542
543template <class ImageType>
544void ImageBaseSlider<ImageType>::setEndPos(const Point<int>& endPos) noexcept
545{
546 pData->endPos = endPos;
547 pData->recheckArea();
548}
549
550template <class ImageType>
551void ImageBaseSlider<ImageType>::setEndPos(int x, int y) noexcept
552{
553 setEndPos(Point<int>(x, y));
554}
555
556template <class ImageType>
557void ImageBaseSlider<ImageType>::setInverted(bool inverted) noexcept
558{
559 if (pData->inverted == inverted)
560 return;
561
562 pData->inverted = inverted;
563 repaint();
564}
565
566template <class ImageType>
567void ImageBaseSlider<ImageType>::setDefault(float value) noexcept
568{
569 pData->valueDef = value;
570 pData->usingDefault = true;
571}
572
573template <class ImageType>
574void ImageBaseSlider<ImageType>::setRange(float min, float max) noexcept
575{
576 pData->minimum = min;
577 pData->maximum = max;
578
579 if (pData->value < min)
580 {
581 pData->value = min;
582 repaint();
583
584 if (pData->callback != nullptr && pData->valueIsSet)
585 {
586 try {
587 pData->callback->imageSliderValueChanged(this, pData->value);
588 } DISTRHO_SAFE_EXCEPTION("ImageBaseSlider::setRange < min");
589 }
590 }
591 else if (pData->value > max)
592 {
593 pData->value = max;
594 repaint();
595
596 if (pData->callback != nullptr && pData->valueIsSet)
597 {
598 try {
599 pData->callback->imageSliderValueChanged(this, pData->value);
600 } DISTRHO_SAFE_EXCEPTION("ImageBaseSlider::setRange > max");
601 }
602 }
603}
604
605template <class ImageType>
606void ImageBaseSlider<ImageType>::setStep(float step) noexcept
607{
608 pData->step = step;
609}
610
611template <class ImageType>
612void ImageBaseSlider<ImageType>::setCallback(Callback* callback) noexcept
613{
614 pData->callback = callback;
615}
616
617template <class ImageType>
618void ImageBaseSlider<ImageType>::onDisplay()
619{
620 const GraphicsContext& context(getGraphicsContext());
621
622#if 0 // DEBUG, paints slider area
623 Color(1.0f, 1.0f, 1.0f, 0.5f).setFor(context, true);
624 Rectangle<int>(pData->sliderArea.getX(),
625 pData->sliderArea.getY(),
626 pData->sliderArea.getX()+pData->sliderArea.getWidth(),
627 pData->sliderArea.getY()+pData->sliderArea.getHeight()).draw(context);
628 Color(1.0f, 1.0f, 1.0f, 1.0f).setFor(context, true);
629#endif
630
631 const float normValue = (pData->value - pData->minimum) / (pData->maximum - pData->minimum);
632
633 int x, y;
634
635 if (pData->startPos.getY() == pData->endPos.getY())
636 {
637 // horizontal
638 if (pData->inverted)
639 x = pData->endPos.getX() - static_cast<int>(normValue*static_cast<float>(pData->endPos.getX()-pData->startPos.getX()));
640 else
641 x = pData->startPos.getX() + static_cast<int>(normValue*static_cast<float>(pData->endPos.getX()-pData->startPos.getX()));
642
643 y = pData->startPos.getY();
644 }
645 else
646 {
647 // vertical
648 x = pData->startPos.getX();
649
650 if (pData->inverted)
651 y = pData->endPos.getY() - static_cast<int>(normValue*static_cast<float>(pData->endPos.getY()-pData->startPos.getY()));
652 else
653 y = pData->startPos.getY() + static_cast<int>(normValue*static_cast<float>(pData->endPos.getY()-pData->startPos.getY()));
654 }
655
656 pData->image.drawAt(context, x, y);
657}
658
659template <class ImageType>
660bool ImageBaseSlider<ImageType>::onMouse(const MouseEvent& ev)
661{
662 if (ev.button != 1)
663 return false;
664
665 if (ev.press)
666 {
667 if (! pData->sliderArea.contains(ev.pos))
668 return false;
669
670 if ((ev.mod & kModifierShift) != 0 && pData->usingDefault)
671 {
672 setValue(pData->valueDef, true);
673 pData->valueTmp = pData->value;
674 return true;
675 }
676
677 float vper;
678 const double x = ev.pos.getX();
679 const double y = ev.pos.getY();
680
681 if (pData->startPos.getY() == pData->endPos.getY())
682 {
683 // horizontal
684 vper = float(x - pData->sliderArea.getX()) / float(pData->sliderArea.getWidth());
685 }
686 else
687 {
688 // vertical
689 vper = float(y - pData->sliderArea.getY()) / float(pData->sliderArea.getHeight());
690 }
691
692 float value;
693
694 if (pData->inverted)
695 value = pData->maximum - vper * (pData->maximum - pData->minimum);
696 else
697 value = pData->minimum + vper * (pData->maximum - pData->minimum);
698
699 if (value < pData->minimum)
700 {
701 pData->valueTmp = value = pData->minimum;
702 }
703 else if (value > pData->maximum)
704 {
705 pData->valueTmp = value = pData->maximum;
706 }
707 else if (d_isNotZero(pData->step))
708 {
709 pData->valueTmp = value;
710 const float rest = std::fmod(value, pData->step);
711 value = value - rest + (rest > pData->step/2.0f ? pData->step : 0.0f);
712 }
713
714 pData->dragging = true;
715 pData->startedX = x;
716 pData->startedY = y;
717
718 if (pData->callback != nullptr)
719 pData->callback->imageSliderDragStarted(this);
720
721 setValue(value, true);
722
723 return true;
724 }
725 else if (pData->dragging)
726 {
727 if (pData->callback != nullptr)
728 pData->callback->imageSliderDragFinished(this);
729
730 pData->dragging = false;
731 return true;
732 }
733
734 return false;
735}
736
737template <class ImageType>
738bool ImageBaseSlider<ImageType>::onMotion(const MotionEvent& ev)
739{
740 if (! pData->dragging)
741 return false;
742
743 const bool horizontal = pData->startPos.getY() == pData->endPos.getY();
744 const double x = ev.pos.getX();
745 const double y = ev.pos.getY();
746
747 if ((horizontal && pData->sliderArea.containsX(x)) || (pData->sliderArea.containsY(y) && ! horizontal))
748 {
749 float vper;
750
751 if (horizontal)
752 {
753 // horizontal
754 vper = float(x - pData->sliderArea.getX()) / float(pData->sliderArea.getWidth());
755 }
756 else
757 {
758 // vertical
759 vper = float(y - pData->sliderArea.getY()) / float(pData->sliderArea.getHeight());
760 }
761
762 float value;
763
764 if (pData->inverted)
765 value = pData->maximum - vper * (pData->maximum - pData->minimum);
766 else
767 value = pData->minimum + vper * (pData->maximum - pData->minimum);
768
769 if (value < pData->minimum)
770 {
771 pData->valueTmp = value = pData->minimum;
772 }
773 else if (value > pData->maximum)
774 {
775 pData->valueTmp = value = pData->maximum;
776 }
777 else if (d_isNotZero(pData->step))
778 {
779 pData->valueTmp = value;
780 const float rest = std::fmod(value, pData->step);
781 value = value - rest + (rest > pData->step/2.0f ? pData->step : 0.0f);
782 }
783
784 setValue(value, true);
785 }
786 else if (horizontal)
787 {
788 if (x < pData->sliderArea.getX())
789 setValue(pData->inverted ? pData->maximum : pData->minimum, true);
790 else
791 setValue(pData->inverted ? pData->minimum : pData->maximum, true);
792 }
793 else
794 {
795 if (y < pData->sliderArea.getY())
796 setValue(pData->inverted ? pData->maximum : pData->minimum, true);
797 else
798 setValue(pData->inverted ? pData->minimum : pData->maximum, true);
799 }
800
801 return true;
802}
803
804// --------------------------------------------------------------------------------------------------------------------
805
806template <class ImageType>
807struct ImageBaseSwitch<ImageType>::PrivateData {
808 ImageType imageNormal;
809 ImageType imageDown;
810 bool isDown;
811 Callback* callback;
812
813 PrivateData(const ImageType& normal, const ImageType& down)
815 imageDown(down),
816 isDown(false),
818 {
819 DISTRHO_SAFE_ASSERT(imageNormal.getSize() == imageDown.getSize());
820 }
821
823 : imageNormal(other->imageNormal),
824 imageDown(other->imageDown),
825 isDown(other->isDown),
826 callback(other->callback)
827 {
828 DISTRHO_SAFE_ASSERT(imageNormal.getSize() == imageDown.getSize());
829 }
830
831 void assignFrom(PrivateData* const other)
832 {
833 imageNormal = other->imageNormal;
834 imageDown = other->imageDown;
835 isDown = other->isDown;
836 callback = other->callback;
837 DISTRHO_SAFE_ASSERT(imageNormal.getSize() == imageDown.getSize());
838 }
839
841};
842
843// --------------------------------------------------------------------------------------------------------------------
844
845template <class ImageType>
846ImageBaseSwitch<ImageType>::ImageBaseSwitch(Widget* const parentWidget, const ImageType& imageNormal, const ImageType& imageDown) noexcept
847 : SubWidget(parentWidget),
848 pData(new PrivateData(imageNormal, imageDown))
849{
850 setSize(imageNormal.getSize());
851}
852
853template <class ImageType>
854ImageBaseSwitch<ImageType>::ImageBaseSwitch(const ImageBaseSwitch<ImageType>& imageSwitch) noexcept
855 : SubWidget(imageSwitch.getParentWidget()),
856 pData(new PrivateData(imageSwitch.pData))
857{
858 setSize(pData->imageNormal.getSize());
859}
860
861template <class ImageType>
862ImageBaseSwitch<ImageType>& ImageBaseSwitch<ImageType>::operator=(const ImageBaseSwitch<ImageType>& imageSwitch) noexcept
863{
864 pData->assignFrom(imageSwitch.pData);
865 setSize(pData->imageNormal.getSize());
866 return *this;
867}
868
869template <class ImageType>
870ImageBaseSwitch<ImageType>::~ImageBaseSwitch()
871{
872 delete pData;
873}
874
875template <class ImageType>
876bool ImageBaseSwitch<ImageType>::isDown() const noexcept
877{
878 return pData->isDown;
879}
880
881template <class ImageType>
882void ImageBaseSwitch<ImageType>::setDown(const bool down) noexcept
883{
884 if (pData->isDown == down)
885 return;
886
887 pData->isDown = down;
888 repaint();
889}
890
891template <class ImageType>
892void ImageBaseSwitch<ImageType>::setCallback(Callback* const callback) noexcept
893{
894 pData->callback = callback;
895}
896
897template <class ImageType>
898void ImageBaseSwitch<ImageType>::onDisplay()
899{
900 const GraphicsContext& context(getGraphicsContext());
901
902 if (pData->isDown)
903 pData->imageDown.draw(context);
904 else
905 pData->imageNormal.draw(context);
906}
907
908template <class ImageType>
909bool ImageBaseSwitch<ImageType>::onMouse(const MouseEvent& ev)
910{
911 if (ev.press && contains(ev.pos))
912 {
913 pData->isDown = !pData->isDown;
914
915 repaint();
916
917 if (pData->callback != nullptr)
918 pData->callback->imageSwitchClicked(this, pData->isDown);
919
920 return true;
921 }
922
923 return false;
924}
925
926// --------------------------------------------------------------------------------------------------------------------
927
928END_NAMESPACE_DGL
unsigned int uint
Definition CarlaDefines.h:327
#define noexcept
Definition DistrhoDefines.h:72
#define DISTRHO_SAFE_ASSERT(cond)
Definition DistrhoDefines.h:104
#define DISTRHO_SAFE_ASSERT_RETURN(cond, ret)
Definition DistrhoDefines.h:112
#define nullptr
Definition DistrhoDefines.h:75
#define DISTRHO_DECLARE_NON_COPYABLE(ClassName)
Definition DistrhoDefines.h:154
#define DISTRHO_SAFE_EXCEPTION(msg)
Definition DistrhoDefines.h:140
uint glTextureId
Definition ImageBaseWidgets.cpp:224
void * cairoSurface
Definition ImageBaseWidgets.cpp:225
float normal(const fft_t *freqs, off_t x)
Definition OscilGen.cpp:46
int y
Definition inflate.c:1588
unsigned x[BMAX+1]
Definition inflate.c:1586
static PuglViewHint int value
Definition pugl.h:1708
static void cleanup(void)
Definition lilv_test.c:152
@ image
Definition juce_AccessibilityRole.h:42
#define false
Definition ordinals.h:83
#define min(x, y)
Definition os.h:74
#define max(x, y)
Definition os.h:78
Definition ImageBaseWidgets.cpp:106
ImageType imageDown
Definition ImageBaseWidgets.cpp:110
ImageBaseButton< ImageType >::Callback * callback
Definition ImageBaseWidgets.cpp:107
PrivateData(const ImageType &normal, const ImageType &hover, const ImageType &down)
Definition ImageBaseWidgets.cpp:112
void buttonClicked(SubWidget *widget, int button) override
Definition ImageBaseWidgets.cpp:118
ImageType imageHover
Definition ImageBaseWidgets.cpp:109
ImageType imageNormal
Definition ImageBaseWidgets.cpp:108
Definition ImageBaseWidgets.cpp:210
PrivateData(const ImageType &img)
Definition ImageBaseWidgets.cpp:228
void assignFrom(PrivateData *const other)
Definition ImageBaseWidgets.cpp:256
~PrivateData()
Definition ImageBaseWidgets.cpp:271
PrivateData(PrivateData *const other)
Definition ImageBaseWidgets.cpp:242
ImageBaseKnob< ImageType >::Callback * callback
Definition ImageBaseWidgets.cpp:211
bool isImgVertical
Definition ImageBaseWidgets.cpp:217
uint imgLayerHeight
Definition ImageBaseWidgets.cpp:219
bool isReady
Definition ImageBaseWidgets.cpp:221
uint imgLayerWidth
Definition ImageBaseWidgets.cpp:218
void knobDragStarted(SubWidget *const widget) override
Definition ImageBaseWidgets.cpp:276
int rotationAngle
Definition ImageBaseWidgets.cpp:214
void knobValueChanged(SubWidget *const widget, const float value) override
Definition ImageBaseWidgets.cpp:290
void knobDragFinished(SubWidget *const widget) override
Definition ImageBaseWidgets.cpp:283
ImageType image
Definition ImageBaseWidgets.cpp:212
bool alwaysRepaint
Definition ImageBaseWidgets.cpp:216
uint imgLayerCount
Definition ImageBaseWidgets.cpp:220
Definition ImageBaseWidgets.cpp:420
ImageType image
Definition ImageBaseWidgets.cpp:421
float value
Definition ImageBaseWidgets.cpp:425
bool dragging
Definition ImageBaseWidgets.cpp:430
bool usingDefault
Definition ImageBaseWidgets.cpp:428
double startedX
Definition ImageBaseWidgets.cpp:433
double startedY
Definition ImageBaseWidgets.cpp:434
PrivateData(const ImageType &img)
Definition ImageBaseWidgets.cpp:442
Point< int > startPos
Definition ImageBaseWidgets.cpp:438
float valueTmp
Definition ImageBaseWidgets.cpp:427
float step
Definition ImageBaseWidgets.cpp:424
Callback * callback
Definition ImageBaseWidgets.cpp:436
Rectangle< double > sliderArea
Definition ImageBaseWidgets.cpp:440
float maximum
Definition ImageBaseWidgets.cpp:423
bool inverted
Definition ImageBaseWidgets.cpp:431
float valueDef
Definition ImageBaseWidgets.cpp:426
bool valueIsSet
Definition ImageBaseWidgets.cpp:432
void recheckArea() noexcept
Definition ImageBaseWidgets.cpp:461
float minimum
Definition ImageBaseWidgets.cpp:422
Point< int > endPos
Definition ImageBaseWidgets.cpp:439
Definition ImageBaseWidgets.cpp:807
ImageType imageNormal
Definition ImageBaseWidgets.cpp:808
bool isDown
Definition ImageBaseWidgets.cpp:810
PrivateData(PrivateData *const other)
Definition ImageBaseWidgets.cpp:822
ImageType imageDown
Definition ImageBaseWidgets.cpp:809
PrivateData(const ImageType &normal, const ImageType &down)
Definition ImageBaseWidgets.cpp:813
Callback * callback
Definition ImageBaseWidgets.cpp:811
void assignFrom(PrivateData *const other)
Definition ImageBaseWidgets.cpp:831
RECT const char void(* callback)(const char *droppath))) SWELL_API_DEFINE(BOOL
Definition swell-functions.h:1004
void Rectangle(HDC ctx, int l, int t, int r, int b)
Definition swell-gdi-generic.cpp:279
ZCONST uch * init
Definition extract.c:2392
_WDL_CSTRING_PREFIX void INT_PTR count
Definition wdlcstring.h:263
#define const
Definition zconf.h:137