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.

199 lines
7.2KB

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