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.

juce_ResizableBorderComponent.cpp 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. ResizableBorderComponent::Zone::Zone() noexcept
  18. : zone (0)
  19. {}
  20. ResizableBorderComponent::Zone::Zone (const int zoneFlags) noexcept
  21. : zone (zoneFlags)
  22. {}
  23. ResizableBorderComponent::Zone::Zone (const ResizableBorderComponent::Zone& other) noexcept
  24. : zone (other.zone)
  25. {}
  26. ResizableBorderComponent::Zone& ResizableBorderComponent::Zone::operator= (const ResizableBorderComponent::Zone& other) noexcept
  27. {
  28. zone = other.zone;
  29. return *this;
  30. }
  31. bool ResizableBorderComponent::Zone::operator== (const ResizableBorderComponent::Zone& other) const noexcept { return zone == other.zone; }
  32. bool ResizableBorderComponent::Zone::operator!= (const ResizableBorderComponent::Zone& other) const noexcept { return zone != other.zone; }
  33. ResizableBorderComponent::Zone ResizableBorderComponent::Zone::fromPositionOnBorder (const Rectangle<int>& totalSize,
  34. const BorderSize<int>& border,
  35. Point<int> position)
  36. {
  37. int z = 0;
  38. if (totalSize.contains (position)
  39. && ! border.subtractedFrom (totalSize).contains (position))
  40. {
  41. const int minW = jmax (totalSize.getWidth() / 10, jmin (10, totalSize.getWidth() / 3));
  42. if (position.x < jmax (border.getLeft(), minW) && border.getLeft() > 0)
  43. z |= left;
  44. else if (position.x >= totalSize.getWidth() - jmax (border.getRight(), minW) && border.getRight() > 0)
  45. z |= right;
  46. const int minH = jmax (totalSize.getHeight() / 10, jmin (10, totalSize.getHeight() / 3));
  47. if (position.y < jmax (border.getTop(), minH) && border.getTop() > 0)
  48. z |= top;
  49. else if (position.y >= totalSize.getHeight() - jmax (border.getBottom(), minH) && border.getBottom() > 0)
  50. z |= bottom;
  51. }
  52. return Zone (z);
  53. }
  54. MouseCursor ResizableBorderComponent::Zone::getMouseCursor() const noexcept
  55. {
  56. MouseCursor::StandardCursorType mc = MouseCursor::NormalCursor;
  57. switch (zone)
  58. {
  59. case (left | top): mc = MouseCursor::TopLeftCornerResizeCursor; break;
  60. case top: mc = MouseCursor::TopEdgeResizeCursor; break;
  61. case (right | top): mc = MouseCursor::TopRightCornerResizeCursor; break;
  62. case left: mc = MouseCursor::LeftEdgeResizeCursor; break;
  63. case right: mc = MouseCursor::RightEdgeResizeCursor; break;
  64. case (left | bottom): mc = MouseCursor::BottomLeftCornerResizeCursor; break;
  65. case bottom: mc = MouseCursor::BottomEdgeResizeCursor; break;
  66. case (right | bottom): mc = MouseCursor::BottomRightCornerResizeCursor; break;
  67. default: break;
  68. }
  69. return mc;
  70. }
  71. //==============================================================================
  72. ResizableBorderComponent::ResizableBorderComponent (Component* const componentToResize,
  73. ComponentBoundsConstrainer* const constrainer_)
  74. : component (componentToResize),
  75. constrainer (constrainer_),
  76. borderSize (5),
  77. mouseZone (0)
  78. {
  79. }
  80. ResizableBorderComponent::~ResizableBorderComponent()
  81. {
  82. }
  83. //==============================================================================
  84. void ResizableBorderComponent::paint (Graphics& g)
  85. {
  86. getLookAndFeel().drawResizableFrame (g, getWidth(), getHeight(), borderSize);
  87. }
  88. void ResizableBorderComponent::mouseEnter (const MouseEvent& e)
  89. {
  90. updateMouseZone (e);
  91. }
  92. void ResizableBorderComponent::mouseMove (const MouseEvent& e)
  93. {
  94. updateMouseZone (e);
  95. }
  96. void ResizableBorderComponent::mouseDown (const MouseEvent& e)
  97. {
  98. if (component == nullptr)
  99. {
  100. jassertfalse; // You've deleted the component that this resizer was supposed to be using!
  101. return;
  102. }
  103. updateMouseZone (e);
  104. originalBounds = component->getBounds();
  105. if (constrainer != nullptr)
  106. constrainer->resizeStart();
  107. }
  108. void ResizableBorderComponent::mouseDrag (const MouseEvent& e)
  109. {
  110. if (component == nullptr)
  111. {
  112. jassertfalse; // You've deleted the component that this resizer was supposed to be using!
  113. return;
  114. }
  115. const Rectangle<int> newBounds (mouseZone.resizeRectangleBy (originalBounds, e.getOffsetFromDragStart()));
  116. if (constrainer != nullptr)
  117. {
  118. constrainer->setBoundsForComponent (component, newBounds,
  119. mouseZone.isDraggingTopEdge(),
  120. mouseZone.isDraggingLeftEdge(),
  121. mouseZone.isDraggingBottomEdge(),
  122. mouseZone.isDraggingRightEdge());
  123. }
  124. else
  125. {
  126. if (Component::Positioner* const pos = component->getPositioner())
  127. pos->applyNewBounds (newBounds);
  128. else
  129. component->setBounds (newBounds);
  130. }
  131. }
  132. void ResizableBorderComponent::mouseUp (const MouseEvent&)
  133. {
  134. if (constrainer != nullptr)
  135. constrainer->resizeEnd();
  136. }
  137. bool ResizableBorderComponent::hitTest (int x, int y)
  138. {
  139. return x < borderSize.getLeft()
  140. || x >= getWidth() - borderSize.getRight()
  141. || y < borderSize.getTop()
  142. || y >= getHeight() - borderSize.getBottom();
  143. }
  144. void ResizableBorderComponent::setBorderThickness (const BorderSize<int>& newBorderSize)
  145. {
  146. if (borderSize != newBorderSize)
  147. {
  148. borderSize = newBorderSize;
  149. repaint();
  150. }
  151. }
  152. BorderSize<int> ResizableBorderComponent::getBorderThickness() const
  153. {
  154. return borderSize;
  155. }
  156. void ResizableBorderComponent::updateMouseZone (const MouseEvent& e)
  157. {
  158. Zone newZone (Zone::fromPositionOnBorder (getLocalBounds(), borderSize, e.getPosition()));
  159. if (mouseZone != newZone)
  160. {
  161. mouseZone = newZone;
  162. setMouseCursor (newZone.getMouseCursor());
  163. }
  164. }