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.

197 lines
6.7KB

  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. namespace juce
  20. {
  21. ResizableBorderComponent::Zone::Zone() noexcept {}
  22. ResizableBorderComponent::Zone::Zone (int zoneFlags) noexcept : zone (zoneFlags) {}
  23. ResizableBorderComponent::Zone::Zone (const ResizableBorderComponent::Zone& other) noexcept : zone (other.zone) {}
  24. ResizableBorderComponent::Zone& ResizableBorderComponent::Zone::operator= (const ResizableBorderComponent::Zone& other) noexcept
  25. {
  26. zone = other.zone;
  27. return *this;
  28. }
  29. bool ResizableBorderComponent::Zone::operator== (const ResizableBorderComponent::Zone& other) const noexcept { return zone == other.zone; }
  30. bool ResizableBorderComponent::Zone::operator!= (const ResizableBorderComponent::Zone& other) const noexcept { return zone != other.zone; }
  31. ResizableBorderComponent::Zone ResizableBorderComponent::Zone::fromPositionOnBorder (Rectangle<int> totalSize,
  32. BorderSize<int> border,
  33. Point<int> position)
  34. {
  35. int z = 0;
  36. if (totalSize.contains (position)
  37. && ! border.subtractedFrom (totalSize).contains (position))
  38. {
  39. auto minW = jmax (totalSize.getWidth() / 10, jmin (10, totalSize.getWidth() / 3));
  40. if (position.x < jmax (border.getLeft(), minW) && border.getLeft() > 0)
  41. z |= left;
  42. else if (position.x >= totalSize.getWidth() - jmax (border.getRight(), minW) && border.getRight() > 0)
  43. z |= right;
  44. auto minH = jmax (totalSize.getHeight() / 10, jmin (10, totalSize.getHeight() / 3));
  45. if (position.y < jmax (border.getTop(), minH) && border.getTop() > 0)
  46. z |= top;
  47. else if (position.y >= totalSize.getHeight() - jmax (border.getBottom(), minH) && border.getBottom() > 0)
  48. z |= bottom;
  49. }
  50. return Zone (z);
  51. }
  52. MouseCursor ResizableBorderComponent::Zone::getMouseCursor() const noexcept
  53. {
  54. auto mc = MouseCursor::NormalCursor;
  55. switch (zone)
  56. {
  57. case (left | top): mc = MouseCursor::TopLeftCornerResizeCursor; break;
  58. case top: mc = MouseCursor::TopEdgeResizeCursor; break;
  59. case (right | top): mc = MouseCursor::TopRightCornerResizeCursor; break;
  60. case left: mc = MouseCursor::LeftEdgeResizeCursor; break;
  61. case right: mc = MouseCursor::RightEdgeResizeCursor; break;
  62. case (left | bottom): mc = MouseCursor::BottomLeftCornerResizeCursor; break;
  63. case bottom: mc = MouseCursor::BottomEdgeResizeCursor; break;
  64. case (right | bottom): mc = MouseCursor::BottomRightCornerResizeCursor; break;
  65. default: break;
  66. }
  67. return mc;
  68. }
  69. //==============================================================================
  70. ResizableBorderComponent::ResizableBorderComponent (Component* componentToResize,
  71. ComponentBoundsConstrainer* boundsConstrainer)
  72. : component (componentToResize),
  73. constrainer (boundsConstrainer),
  74. borderSize (5)
  75. {
  76. }
  77. ResizableBorderComponent::~ResizableBorderComponent() = default;
  78. //==============================================================================
  79. void ResizableBorderComponent::paint (Graphics& g)
  80. {
  81. getLookAndFeel().drawResizableFrame (g, getWidth(), getHeight(), borderSize);
  82. }
  83. void ResizableBorderComponent::mouseEnter (const MouseEvent& e)
  84. {
  85. updateMouseZone (e);
  86. }
  87. void ResizableBorderComponent::mouseMove (const MouseEvent& e)
  88. {
  89. updateMouseZone (e);
  90. }
  91. void ResizableBorderComponent::mouseDown (const MouseEvent& e)
  92. {
  93. if (component == nullptr)
  94. {
  95. jassertfalse; // You've deleted the component that this resizer was supposed to be using!
  96. return;
  97. }
  98. updateMouseZone (e);
  99. originalBounds = component->getBounds();
  100. if (constrainer != nullptr)
  101. constrainer->resizeStart();
  102. }
  103. void ResizableBorderComponent::mouseDrag (const MouseEvent& e)
  104. {
  105. if (component == nullptr)
  106. {
  107. jassertfalse; // You've deleted the component that this resizer was supposed to be using!
  108. return;
  109. }
  110. auto newBounds = mouseZone.resizeRectangleBy (originalBounds, e.getOffsetFromDragStart());
  111. if (constrainer != nullptr)
  112. {
  113. constrainer->setBoundsForComponent (component, newBounds,
  114. mouseZone.isDraggingTopEdge(),
  115. mouseZone.isDraggingLeftEdge(),
  116. mouseZone.isDraggingBottomEdge(),
  117. mouseZone.isDraggingRightEdge());
  118. }
  119. else
  120. {
  121. if (auto* p = component->getPositioner())
  122. p->applyNewBounds (newBounds);
  123. else
  124. component->setBounds (newBounds);
  125. }
  126. }
  127. void ResizableBorderComponent::mouseUp (const MouseEvent&)
  128. {
  129. if (constrainer != nullptr)
  130. constrainer->resizeEnd();
  131. }
  132. bool ResizableBorderComponent::hitTest (int x, int y)
  133. {
  134. return ! borderSize.subtractedFrom (getLocalBounds()).contains (x, y);
  135. }
  136. void ResizableBorderComponent::setBorderThickness (BorderSize<int> newBorderSize)
  137. {
  138. if (borderSize != newBorderSize)
  139. {
  140. borderSize = newBorderSize;
  141. repaint();
  142. }
  143. }
  144. BorderSize<int> ResizableBorderComponent::getBorderThickness() const
  145. {
  146. return borderSize;
  147. }
  148. void ResizableBorderComponent::updateMouseZone (const MouseEvent& e)
  149. {
  150. auto newZone = Zone::fromPositionOnBorder (getLocalBounds(), borderSize, e.getPosition());
  151. if (mouseZone != newZone)
  152. {
  153. mouseZone = newZone;
  154. setMouseCursor (newZone.getMouseCursor());
  155. }
  156. }
  157. } // namespace juce