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.

328 lines
11KB

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