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.

155 lines
5.1KB

  1. #ifndef MAINCOMPONENT_H_INCLUDED
  2. #define MAINCOMPONENT_H_INCLUDED
  3. #include "../JuceLibraryCode/JuceHeader.h"
  4. #include "BlockComponents.h"
  5. /**
  6. The main component where the Block components will be displayed
  7. */
  8. class MainComponent : public Component,
  9. public TopologySource::Listener,
  10. private Timer
  11. {
  12. public:
  13. MainComponent()
  14. {
  15. setSize (600, 600);
  16. noBlocksLabel.setText ("No BLOCKS connected...", dontSendNotification);
  17. noBlocksLabel.setJustificationType (Justification::centred);
  18. addAndMakeVisible (noBlocksLabel);
  19. // Register MainComponent as a listener to the PhysicalTopologySource object
  20. topologySource.addListener (this);
  21. startTimer (10000);
  22. }
  23. void paint (Graphics& g) override
  24. {
  25. g.fillAll (Colours::lightgrey);
  26. }
  27. void resized() override
  28. {
  29. noBlocksLabel.setVisible (false);
  30. const int numBlockComponents = blockComponents.size();
  31. // If there are no currently connected Blocks then display some text on the screen
  32. if (numBlockComponents == 0)
  33. {
  34. noBlocksLabel.setVisible (true);
  35. noBlocksLabel.setBounds (0, (getHeight() / 2) - 50, getWidth(), 100);
  36. return;
  37. }
  38. // Work out the maximum diplay area for each Block
  39. auto bounds = getLocalBounds().reduced (20);
  40. auto squareRoot = std::sqrt (numBlockComponents);
  41. int gridSize = (int) squareRoot;
  42. if (squareRoot - gridSize > 0)
  43. gridSize++;
  44. int sideLength = bounds.getWidth() / gridSize;
  45. int xCounter = 0;
  46. int yCounter = 0;
  47. bool hasSpaceForControlBlock = false;
  48. Rectangle<int> lastControlBlockBounds;
  49. for (auto block : blockComponents)
  50. {
  51. Rectangle<int> blockBounds;
  52. auto type = block->block->getType();
  53. // Can fit 2 ControlBlockComponents in the space of one LightpadBlockComponent
  54. if (type == Block::liveBlock || type == Block::loopBlock)
  55. {
  56. if (hasSpaceForControlBlock)
  57. {
  58. blockBounds = lastControlBlockBounds.withY (lastControlBlockBounds.getY() + (int)(sideLength * 0.5));
  59. hasSpaceForControlBlock = false;
  60. }
  61. else
  62. {
  63. blockBounds = Rectangle<int> (bounds.getX() + (xCounter * sideLength), bounds.getY() + (yCounter * sideLength),
  64. sideLength, (int)(sideLength * 0.5));
  65. hasSpaceForControlBlock = true;
  66. lastControlBlockBounds = blockBounds;
  67. }
  68. }
  69. else
  70. {
  71. blockBounds = Rectangle<int> (bounds.getX() + (xCounter * sideLength), bounds.getY() + (yCounter * sideLength),
  72. sideLength, sideLength);
  73. }
  74. block->setBounds (blockBounds.reduced (5));
  75. if (++xCounter >= gridSize)
  76. {
  77. yCounter++;
  78. xCounter = 0;
  79. }
  80. }
  81. }
  82. /** Overridden from TopologySource::Listener, called when the topology changes */
  83. void topologyChanged() override
  84. {
  85. // Clear the array of Block components
  86. blockComponents.clear();
  87. // Get the array of currently connected Block objects from the PhysicalTopologySource
  88. auto blocksArray = topologySource.getCurrentTopology().blocks;
  89. // Create a BlockComponent object for each Block object
  90. for (auto& block : blocksArray)
  91. if (auto* blockComponent = createBlockComponent (block))
  92. addAndMakeVisible (blockComponents.add (blockComponent));
  93. // Update the display
  94. resized();
  95. }
  96. private:
  97. /** Creates a BlockComponent object for a new Block and adds it to the content component */
  98. BlockComponent* createBlockComponent (Block::Ptr newBlock)
  99. {
  100. auto type = newBlock->getType();
  101. if (type == Block::lightPadBlock)
  102. return new LightpadComponent (newBlock);
  103. if (type == Block::loopBlock || type == Block::liveBlock)
  104. return new ControlBlockComponent (newBlock);
  105. // should only be connecting a Lightpad or Control Block!
  106. jassertfalse;
  107. return nullptr;
  108. }
  109. /** Periodically updates the displayed BlockComponent tooltips */
  110. void timerCallback() override
  111. {
  112. for (auto c : blockComponents)
  113. c->updateStatsAndTooltip();
  114. }
  115. //==============================================================================
  116. PhysicalTopologySource topologySource;
  117. OwnedArray<BlockComponent> blockComponents;
  118. Label noBlocksLabel;
  119. //==============================================================================
  120. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
  121. };
  122. #endif // MAINCOMPONENT_H_INCLUDED