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.

290 lines
9.9KB

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