The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

135 lines
3.9KB

  1. #pragma once
  2. //==============================================================================
  3. /**
  4. Represents a single LED on a Lightpad
  5. */
  6. struct LEDComponent : public Component
  7. {
  8. LEDComponent() : ledColour (Colours::black) { setInterceptsMouseClicks (false, false); }
  9. void setColour (Colour newColour)
  10. {
  11. ledColour = newColour;
  12. repaint();
  13. }
  14. void paint (Graphics& g) override
  15. {
  16. g.setColour (ledColour);
  17. g.fillEllipse (getLocalBounds().toFloat());
  18. }
  19. Colour ledColour;
  20. };
  21. //==============================================================================
  22. /**
  23. A component that is used to represent a Lightpad on-screen
  24. */
  25. class LightpadComponent : public Component
  26. {
  27. public:
  28. LightpadComponent ()
  29. {
  30. for (int x = 0; x < 15; ++x)
  31. for (int y = 0; y < 15; ++y)
  32. addAndMakeVisible (leds.add (new LEDComponent()));
  33. }
  34. void paint (Graphics& g) override
  35. {
  36. auto r = getLocalBounds().toFloat();
  37. // Clip the drawing area to only draw in the block area
  38. {
  39. Path clipArea;
  40. clipArea.addRoundedRectangle (r, r.getWidth() / 20.0f);
  41. g.reduceClipRegion (clipArea);
  42. }
  43. // Fill a black square for the Lightpad
  44. g.fillAll (Colours::black);
  45. }
  46. void resized() override
  47. {
  48. Rectangle<int> r = getLocalBounds().reduced (10);
  49. int circleWidth = r.getWidth() / 15;
  50. int circleHeight = r.getHeight() / 15;
  51. for (int x = 0; x < 15; ++x)
  52. for (int y = 0; y < 15; ++y)
  53. leds.getUnchecked ((x * 15) + y)->setBounds (r.getX() + (x * circleWidth),
  54. r.getY() + (y * circleHeight),
  55. circleWidth, circleHeight);
  56. }
  57. void mouseDown (const MouseEvent& e) override
  58. {
  59. for (int x = 0; x < 15; ++x)
  60. {
  61. for (int y = 0; y < 15; ++y)
  62. {
  63. if (leds.getUnchecked ((x * 15) + y)->getBounds().contains (e.position.toInt()))
  64. {
  65. listeners.call (&Listener::ledClicked, x, y, e.pressure);
  66. }
  67. }
  68. }
  69. }
  70. void mouseDrag (const MouseEvent& e) override
  71. {
  72. for (int x = 0; x < 15; ++x)
  73. {
  74. for (int y = 0; y < 15; ++y)
  75. {
  76. if (leds.getUnchecked ((x * 15) + y)->getBounds().contains (e.position.toInt()))
  77. {
  78. const Time t = e.eventTime;
  79. if (lastLED == Point<int> (x, y) && t.toMilliseconds() - lastMouseEventTime.toMilliseconds() < 50)
  80. return;
  81. listeners.call (&Listener::ledClicked, x, y, e.pressure);
  82. lastLED = Point<int> (x, y);
  83. lastMouseEventTime = t;
  84. }
  85. }
  86. }
  87. }
  88. //==============================================================================
  89. /** Sets the colour of one of the LEDComponents */
  90. void setLEDColour (int x, int y, Colour c)
  91. {
  92. x = jmin (x, 14);
  93. y = jmin (y, 14);
  94. leds.getUnchecked ((x * 15) + y)->setColour (c);
  95. }
  96. //==============================================================================
  97. struct Listener
  98. {
  99. virtual ~Listener() {}
  100. /** Called when an LEDComponent has been clicked */
  101. virtual void ledClicked (int x, int y, float z) = 0;
  102. };
  103. void addListener (Listener* l) { listeners.add (l); }
  104. void removeListener (Listener* l) { listeners.remove (l); }
  105. private:
  106. OwnedArray<LEDComponent> leds;
  107. ListenerList<Listener> listeners;
  108. Time lastMouseEventTime;
  109. Point<int> lastLED;
  110. };