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.

117 lines
3.9KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. StretchableObjectResizer::StretchableObjectResizer() {}
  18. StretchableObjectResizer::~StretchableObjectResizer() {}
  19. void StretchableObjectResizer::addItem (const double size,
  20. const double minSize, const double maxSize,
  21. const int order)
  22. {
  23. // the order must be >= 0 but less than the maximum integer value.
  24. jassert (order >= 0 && order < std::numeric_limits<int>::max());
  25. jassert (maxSize >= minSize);
  26. Item item;
  27. item.size = size;
  28. item.minSize = minSize;
  29. item.maxSize = maxSize;
  30. item.order = order;
  31. items.add (item);
  32. }
  33. double StretchableObjectResizer::getItemSize (const int index) const noexcept
  34. {
  35. return isPositiveAndBelow (index, items.size()) ? items.getReference (index).size
  36. : 0.0;
  37. }
  38. void StretchableObjectResizer::resizeToFit (const double targetSize)
  39. {
  40. int order = 0;
  41. for (;;)
  42. {
  43. double currentSize = 0;
  44. double minSize = 0;
  45. double maxSize = 0;
  46. int nextHighestOrder = std::numeric_limits<int>::max();
  47. for (int i = 0; i < items.size(); ++i)
  48. {
  49. const Item& it = items.getReference(i);
  50. currentSize += it.size;
  51. if (it.order <= order)
  52. {
  53. minSize += it.minSize;
  54. maxSize += it.maxSize;
  55. }
  56. else
  57. {
  58. minSize += it.size;
  59. maxSize += it.size;
  60. nextHighestOrder = jmin (nextHighestOrder, it.order);
  61. }
  62. }
  63. const double thisIterationTarget = jlimit (minSize, maxSize, targetSize);
  64. if (thisIterationTarget >= currentSize)
  65. {
  66. const double availableExtraSpace = maxSize - currentSize;
  67. const double targetAmountOfExtraSpace = thisIterationTarget - currentSize;
  68. const double scale = availableExtraSpace > 0 ? targetAmountOfExtraSpace / availableExtraSpace : 1.0;
  69. for (int i = 0; i < items.size(); ++i)
  70. {
  71. Item& it = items.getReference(i);
  72. if (it.order <= order)
  73. it.size = jlimit (it.minSize, it.maxSize, it.size + (it.maxSize - it.size) * scale);
  74. }
  75. }
  76. else
  77. {
  78. const double amountOfSlack = currentSize - minSize;
  79. const double targetAmountOfSlack = thisIterationTarget - minSize;
  80. const double scale = targetAmountOfSlack / amountOfSlack;
  81. for (int i = 0; i < items.size(); ++i)
  82. {
  83. Item& it = items.getReference(i);
  84. if (it.order <= order)
  85. it.size = jmax (it.minSize, it.minSize + (it.size - it.minSize) * scale);
  86. }
  87. }
  88. if (nextHighestOrder < std::numeric_limits<int>::max())
  89. order = nextHighestOrder;
  90. else
  91. break;
  92. }
  93. }