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.

293 lines
10KB

  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. ComponentBoundsConstrainer::ComponentBoundsConstrainer() noexcept {}
  20. ComponentBoundsConstrainer::~ComponentBoundsConstrainer() {}
  21. //==============================================================================
  22. void ComponentBoundsConstrainer::setMinimumWidth (int minimumWidth) noexcept { minW = minimumWidth; }
  23. void ComponentBoundsConstrainer::setMaximumWidth (int maximumWidth) noexcept { maxW = maximumWidth; }
  24. void ComponentBoundsConstrainer::setMinimumHeight (int minimumHeight) noexcept { minH = minimumHeight; }
  25. void ComponentBoundsConstrainer::setMaximumHeight (int maximumHeight) noexcept { maxH = maximumHeight; }
  26. void ComponentBoundsConstrainer::setMinimumSize (int minimumWidth, int minimumHeight) noexcept
  27. {
  28. jassert (maxW >= minimumWidth);
  29. jassert (maxH >= minimumHeight);
  30. jassert (minimumWidth > 0 && minimumHeight > 0);
  31. minW = minimumWidth;
  32. minH = minimumHeight;
  33. if (minW > maxW) maxW = minW;
  34. if (minH > maxH) maxH = minH;
  35. }
  36. void ComponentBoundsConstrainer::setMaximumSize (int maximumWidth, int maximumHeight) noexcept
  37. {
  38. jassert (maximumWidth >= minW);
  39. jassert (maximumHeight >= minH);
  40. jassert (maximumWidth > 0 && maximumHeight > 0);
  41. maxW = jmax (minW, maximumWidth);
  42. maxH = jmax (minH, maximumHeight);
  43. }
  44. void ComponentBoundsConstrainer::setSizeLimits (int minimumWidth,
  45. int minimumHeight,
  46. int maximumWidth,
  47. int maximumHeight) noexcept
  48. {
  49. jassert (maximumWidth >= minimumWidth);
  50. jassert (maximumHeight >= minimumHeight);
  51. jassert (maximumWidth > 0 && maximumHeight > 0);
  52. jassert (minimumWidth > 0 && minimumHeight > 0);
  53. minW = jmax (0, minimumWidth);
  54. minH = jmax (0, minimumHeight);
  55. maxW = jmax (minW, maximumWidth);
  56. maxH = jmax (minH, maximumHeight);
  57. }
  58. void ComponentBoundsConstrainer::setMinimumOnscreenAmounts (int minimumWhenOffTheTop,
  59. int minimumWhenOffTheLeft,
  60. int minimumWhenOffTheBottom,
  61. int minimumWhenOffTheRight) noexcept
  62. {
  63. minOffTop = minimumWhenOffTheTop;
  64. minOffLeft = minimumWhenOffTheLeft;
  65. minOffBottom = minimumWhenOffTheBottom;
  66. minOffRight = minimumWhenOffTheRight;
  67. }
  68. void ComponentBoundsConstrainer::setFixedAspectRatio (double widthOverHeight) noexcept
  69. {
  70. aspectRatio = jmax (0.0, widthOverHeight);
  71. }
  72. double ComponentBoundsConstrainer::getFixedAspectRatio() const noexcept
  73. {
  74. return aspectRatio;
  75. }
  76. void ComponentBoundsConstrainer::setBoundsForComponent (Component* component,
  77. Rectangle<int> targetBounds,
  78. bool isStretchingTop,
  79. bool isStretchingLeft,
  80. bool isStretchingBottom,
  81. bool isStretchingRight)
  82. {
  83. jassert (component != nullptr);
  84. Rectangle<int> limits, bounds (targetBounds);
  85. BorderSize<int> border;
  86. if (auto* parent = component->getParentComponent())
  87. {
  88. limits.setSize (parent->getWidth(), parent->getHeight());
  89. }
  90. else
  91. {
  92. if (auto* peer = component->getPeer())
  93. border = peer->getFrameSize();
  94. auto screenBounds = Desktop::getInstance().getDisplays().getDisplayContaining (targetBounds.getCentre()).userArea;
  95. limits = component->getLocalArea (nullptr, screenBounds) + component->getPosition();
  96. }
  97. border.addTo (bounds);
  98. checkBounds (bounds,
  99. border.addedTo (component->getBounds()), limits,
  100. isStretchingTop, isStretchingLeft,
  101. isStretchingBottom, isStretchingRight);
  102. border.subtractFrom (bounds);
  103. applyBoundsToComponent (*component, bounds);
  104. }
  105. void ComponentBoundsConstrainer::checkComponentBounds (Component* component)
  106. {
  107. setBoundsForComponent (component, component->getBounds(),
  108. false, false, false, false);
  109. }
  110. void ComponentBoundsConstrainer::applyBoundsToComponent (Component& component, Rectangle<int> bounds)
  111. {
  112. if (auto* positioner = component.getPositioner())
  113. positioner->applyNewBounds (bounds);
  114. else
  115. component.setBounds (bounds);
  116. }
  117. //==============================================================================
  118. void ComponentBoundsConstrainer::resizeStart()
  119. {
  120. }
  121. void ComponentBoundsConstrainer::resizeEnd()
  122. {
  123. }
  124. //==============================================================================
  125. void ComponentBoundsConstrainer::checkBounds (Rectangle<int>& bounds,
  126. const Rectangle<int>& old,
  127. const Rectangle<int>& limits,
  128. bool isStretchingTop,
  129. bool isStretchingLeft,
  130. bool isStretchingBottom,
  131. bool isStretchingRight)
  132. {
  133. if (isStretchingLeft)
  134. bounds.setLeft (jlimit (old.getRight() - maxW, old.getRight() - minW, bounds.getX()));
  135. else
  136. bounds.setWidth (jlimit (minW, maxW, bounds.getWidth()));
  137. if (isStretchingTop)
  138. bounds.setTop (jlimit (old.getBottom() - maxH, old.getBottom() - minH, bounds.getY()));
  139. else
  140. bounds.setHeight (jlimit (minH, maxH, bounds.getHeight()));
  141. if (bounds.isEmpty())
  142. return;
  143. if (minOffTop > 0)
  144. {
  145. const int limit = limits.getY() + jmin (minOffTop - bounds.getHeight(), 0);
  146. if (bounds.getY() < limit)
  147. {
  148. if (isStretchingTop)
  149. bounds.setTop (limits.getY());
  150. else
  151. bounds.setY (limit);
  152. }
  153. }
  154. if (minOffLeft > 0)
  155. {
  156. const int limit = limits.getX() + jmin (minOffLeft - bounds.getWidth(), 0);
  157. if (bounds.getX() < limit)
  158. {
  159. if (isStretchingLeft)
  160. bounds.setLeft (limits.getX());
  161. else
  162. bounds.setX (limit);
  163. }
  164. }
  165. if (minOffBottom > 0)
  166. {
  167. const int limit = limits.getBottom() - jmin (minOffBottom, bounds.getHeight());
  168. if (bounds.getY() > limit)
  169. {
  170. if (isStretchingBottom)
  171. bounds.setBottom (limits.getBottom());
  172. else
  173. bounds.setY (limit);
  174. }
  175. }
  176. if (minOffRight > 0)
  177. {
  178. const int limit = limits.getRight() - jmin (minOffRight, bounds.getWidth());
  179. if (bounds.getX() > limit)
  180. {
  181. if (isStretchingRight)
  182. bounds.setRight (limits.getRight());
  183. else
  184. bounds.setX (limit);
  185. }
  186. }
  187. // constrain the aspect ratio if one has been specified..
  188. if (aspectRatio > 0.0)
  189. {
  190. bool adjustWidth;
  191. if ((isStretchingTop || isStretchingBottom) && ! (isStretchingLeft || isStretchingRight))
  192. {
  193. adjustWidth = true;
  194. }
  195. else if ((isStretchingLeft || isStretchingRight) && ! (isStretchingTop || isStretchingBottom))
  196. {
  197. adjustWidth = false;
  198. }
  199. else
  200. {
  201. const double oldRatio = (old.getHeight() > 0) ? std::abs (old.getWidth() / (double) old.getHeight()) : 0.0;
  202. const double newRatio = std::abs (bounds.getWidth() / (double) bounds.getHeight());
  203. adjustWidth = (oldRatio > newRatio);
  204. }
  205. if (adjustWidth)
  206. {
  207. bounds.setWidth (roundToInt (bounds.getHeight() * aspectRatio));
  208. if (bounds.getWidth() > maxW || bounds.getWidth() < minW)
  209. {
  210. bounds.setWidth (jlimit (minW, maxW, bounds.getWidth()));
  211. bounds.setHeight (roundToInt (bounds.getWidth() / aspectRatio));
  212. }
  213. }
  214. else
  215. {
  216. bounds.setHeight (roundToInt (bounds.getWidth() / aspectRatio));
  217. if (bounds.getHeight() > maxH || bounds.getHeight() < minH)
  218. {
  219. bounds.setHeight (jlimit (minH, maxH, bounds.getHeight()));
  220. bounds.setWidth (roundToInt (bounds.getHeight() * aspectRatio));
  221. }
  222. }
  223. if ((isStretchingTop || isStretchingBottom) && ! (isStretchingLeft || isStretchingRight))
  224. {
  225. bounds.setX (old.getX() + (old.getWidth() - bounds.getWidth()) / 2);
  226. }
  227. else if ((isStretchingLeft || isStretchingRight) && ! (isStretchingTop || isStretchingBottom))
  228. {
  229. bounds.setY (old.getY() + (old.getHeight() - bounds.getHeight()) / 2);
  230. }
  231. else
  232. {
  233. if (isStretchingLeft)
  234. bounds.setX (old.getRight() - bounds.getWidth());
  235. if (isStretchingTop)
  236. bounds.setY (old.getBottom() - bounds.getHeight());
  237. }
  238. }
  239. jassert (! bounds.isEmpty());
  240. }