Audio plugin host https://kx.studio/carla
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.

204 lines
6.9KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. ResizableBorderComponent::Zone::Zone() noexcept
  20. : zone (0)
  21. {}
  22. ResizableBorderComponent::Zone::Zone (const int zoneFlags) noexcept
  23. : zone (zoneFlags)
  24. {}
  25. ResizableBorderComponent::Zone::Zone (const ResizableBorderComponent::Zone& other) noexcept
  26. : zone (other.zone)
  27. {}
  28. ResizableBorderComponent::Zone& ResizableBorderComponent::Zone::operator= (const ResizableBorderComponent::Zone& other) noexcept
  29. {
  30. zone = other.zone;
  31. return *this;
  32. }
  33. bool ResizableBorderComponent::Zone::operator== (const ResizableBorderComponent::Zone& other) const noexcept { return zone == other.zone; }
  34. bool ResizableBorderComponent::Zone::operator!= (const ResizableBorderComponent::Zone& other) const noexcept { return zone != other.zone; }
  35. ResizableBorderComponent::Zone ResizableBorderComponent::Zone::fromPositionOnBorder (const Rectangle<int>& totalSize,
  36. const BorderSize<int>& border,
  37. Point<int> position)
  38. {
  39. int z = 0;
  40. if (totalSize.contains (position)
  41. && ! border.subtractedFrom (totalSize).contains (position))
  42. {
  43. const int minW = jmax (totalSize.getWidth() / 10, jmin (10, totalSize.getWidth() / 3));
  44. if (position.x < jmax (border.getLeft(), minW) && border.getLeft() > 0)
  45. z |= left;
  46. else if (position.x >= totalSize.getWidth() - jmax (border.getRight(), minW) && border.getRight() > 0)
  47. z |= right;
  48. const int minH = jmax (totalSize.getHeight() / 10, jmin (10, totalSize.getHeight() / 3));
  49. if (position.y < jmax (border.getTop(), minH) && border.getTop() > 0)
  50. z |= top;
  51. else if (position.y >= totalSize.getHeight() - jmax (border.getBottom(), minH) && border.getBottom() > 0)
  52. z |= bottom;
  53. }
  54. return Zone (z);
  55. }
  56. MouseCursor ResizableBorderComponent::Zone::getMouseCursor() const noexcept
  57. {
  58. MouseCursor::StandardCursorType mc = MouseCursor::NormalCursor;
  59. switch (zone)
  60. {
  61. case (left | top): mc = MouseCursor::TopLeftCornerResizeCursor; break;
  62. case top: mc = MouseCursor::TopEdgeResizeCursor; break;
  63. case (right | top): mc = MouseCursor::TopRightCornerResizeCursor; break;
  64. case left: mc = MouseCursor::LeftEdgeResizeCursor; break;
  65. case right: mc = MouseCursor::RightEdgeResizeCursor; break;
  66. case (left | bottom): mc = MouseCursor::BottomLeftCornerResizeCursor; break;
  67. case bottom: mc = MouseCursor::BottomEdgeResizeCursor; break;
  68. case (right | bottom): mc = MouseCursor::BottomRightCornerResizeCursor; break;
  69. default: break;
  70. }
  71. return mc;
  72. }
  73. //==============================================================================
  74. ResizableBorderComponent::ResizableBorderComponent (Component* const componentToResize,
  75. ComponentBoundsConstrainer* const constrainer_)
  76. : component (componentToResize),
  77. constrainer (constrainer_),
  78. borderSize (5),
  79. mouseZone (0)
  80. {
  81. }
  82. ResizableBorderComponent::~ResizableBorderComponent()
  83. {
  84. }
  85. //==============================================================================
  86. void ResizableBorderComponent::paint (Graphics& g)
  87. {
  88. getLookAndFeel().drawResizableFrame (g, getWidth(), getHeight(), borderSize);
  89. }
  90. void ResizableBorderComponent::mouseEnter (const MouseEvent& e)
  91. {
  92. updateMouseZone (e);
  93. }
  94. void ResizableBorderComponent::mouseMove (const MouseEvent& e)
  95. {
  96. updateMouseZone (e);
  97. }
  98. void ResizableBorderComponent::mouseDown (const MouseEvent& e)
  99. {
  100. if (component == nullptr)
  101. {
  102. jassertfalse; // You've deleted the component that this resizer was supposed to be using!
  103. return;
  104. }
  105. updateMouseZone (e);
  106. originalBounds = component->getBounds();
  107. if (constrainer != nullptr)
  108. constrainer->resizeStart();
  109. }
  110. void ResizableBorderComponent::mouseDrag (const MouseEvent& e)
  111. {
  112. if (component == nullptr)
  113. {
  114. jassertfalse; // You've deleted the component that this resizer was supposed to be using!
  115. return;
  116. }
  117. const Rectangle<int> newBounds (mouseZone.resizeRectangleBy (originalBounds, e.getOffsetFromDragStart()));
  118. if (constrainer != nullptr)
  119. {
  120. constrainer->setBoundsForComponent (component, newBounds,
  121. mouseZone.isDraggingTopEdge(),
  122. mouseZone.isDraggingLeftEdge(),
  123. mouseZone.isDraggingBottomEdge(),
  124. mouseZone.isDraggingRightEdge());
  125. }
  126. else
  127. {
  128. if (Component::Positioner* const pos = component->getPositioner())
  129. pos->applyNewBounds (newBounds);
  130. else
  131. component->setBounds (newBounds);
  132. }
  133. }
  134. void ResizableBorderComponent::mouseUp (const MouseEvent&)
  135. {
  136. if (constrainer != nullptr)
  137. constrainer->resizeEnd();
  138. }
  139. bool ResizableBorderComponent::hitTest (int x, int y)
  140. {
  141. return x < borderSize.getLeft()
  142. || x >= getWidth() - borderSize.getRight()
  143. || y < borderSize.getTop()
  144. || y >= getHeight() - borderSize.getBottom();
  145. }
  146. void ResizableBorderComponent::setBorderThickness (const BorderSize<int>& newBorderSize)
  147. {
  148. if (borderSize != newBorderSize)
  149. {
  150. borderSize = newBorderSize;
  151. repaint();
  152. }
  153. }
  154. BorderSize<int> ResizableBorderComponent::getBorderThickness() const
  155. {
  156. return borderSize;
  157. }
  158. void ResizableBorderComponent::updateMouseZone (const MouseEvent& e)
  159. {
  160. Zone newZone (Zone::fromPositionOnBorder (getLocalBounds(), borderSize, e.getPosition()));
  161. if (mouseZone != newZone)
  162. {
  163. mouseZone = newZone;
  164. setMouseCursor (newZone.getMouseCursor());
  165. }
  166. }