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.

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