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.

201 lines
7.1KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. ResizableBorderComponent::Zone::Zone (const int zoneFlags) noexcept
  19. : zone (zoneFlags)
  20. {}
  21. ResizableBorderComponent::Zone::Zone (const ResizableBorderComponent::Zone& other) noexcept
  22. : zone (other.zone)
  23. {}
  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. const ResizableBorderComponent::Zone ResizableBorderComponent::Zone::fromPositionOnBorder (const Rectangle<int>& totalSize,
  32. const BorderSize<int>& border,
  33. const Point<int>& position)
  34. {
  35. int z = 0;
  36. if (totalSize.contains (position)
  37. && ! border.subtractedFrom (totalSize).contains (position))
  38. {
  39. const int 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. const int 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. MouseCursor::StandardCursorType 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* const componentToResize,
  71. ComponentBoundsConstrainer* const constrainer_)
  72. : component (componentToResize),
  73. constrainer (constrainer_),
  74. borderSize (5),
  75. mouseZone (0)
  76. {
  77. }
  78. ResizableBorderComponent::~ResizableBorderComponent()
  79. {
  80. }
  81. //==============================================================================
  82. void ResizableBorderComponent::paint (Graphics& g)
  83. {
  84. getLookAndFeel().drawResizableFrame (g, getWidth(), getHeight(), borderSize);
  85. }
  86. void ResizableBorderComponent::mouseEnter (const MouseEvent& e)
  87. {
  88. updateMouseZone (e);
  89. }
  90. void ResizableBorderComponent::mouseMove (const MouseEvent& e)
  91. {
  92. updateMouseZone (e);
  93. }
  94. void ResizableBorderComponent::mouseDown (const MouseEvent& e)
  95. {
  96. if (component == nullptr)
  97. {
  98. jassertfalse; // You've deleted the component that this resizer was supposed to be using!
  99. return;
  100. }
  101. updateMouseZone (e);
  102. originalBounds = component->getBounds();
  103. if (constrainer != nullptr)
  104. constrainer->resizeStart();
  105. }
  106. void ResizableBorderComponent::mouseDrag (const MouseEvent& e)
  107. {
  108. if (component == nullptr)
  109. {
  110. jassertfalse; // You've deleted the component that this resizer was supposed to be using!
  111. return;
  112. }
  113. const Rectangle<int> newBounds (mouseZone.resizeRectangleBy (originalBounds, e.getOffsetFromDragStart()));
  114. if (constrainer != nullptr)
  115. {
  116. constrainer->setBoundsForComponent (component, newBounds,
  117. mouseZone.isDraggingTopEdge(),
  118. mouseZone.isDraggingLeftEdge(),
  119. mouseZone.isDraggingBottomEdge(),
  120. mouseZone.isDraggingRightEdge());
  121. }
  122. else
  123. {
  124. Component::Positioner* const pos = component->getPositioner();
  125. if (pos != nullptr)
  126. pos->applyNewBounds (newBounds);
  127. else
  128. component->setBounds (newBounds);
  129. }
  130. }
  131. void ResizableBorderComponent::mouseUp (const MouseEvent&)
  132. {
  133. if (constrainer != nullptr)
  134. constrainer->resizeEnd();
  135. }
  136. bool ResizableBorderComponent::hitTest (int x, int y)
  137. {
  138. return x < borderSize.getLeft()
  139. || x >= getWidth() - borderSize.getRight()
  140. || y < borderSize.getTop()
  141. || y >= getHeight() - borderSize.getBottom();
  142. }
  143. void ResizableBorderComponent::setBorderThickness (const BorderSize<int>& newBorderSize)
  144. {
  145. if (borderSize != newBorderSize)
  146. {
  147. borderSize = newBorderSize;
  148. repaint();
  149. }
  150. }
  151. BorderSize<int> ResizableBorderComponent::getBorderThickness() const
  152. {
  153. return borderSize;
  154. }
  155. void ResizableBorderComponent::updateMouseZone (const MouseEvent& e)
  156. {
  157. Zone newZone (Zone::fromPositionOnBorder (getLocalBounds(), borderSize, e.getPosition()));
  158. if (mouseZone != newZone)
  159. {
  160. mouseZone = newZone;
  161. setMouseCursor (newZone.getMouseCursor());
  162. }
  163. }