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.

123 lines
3.9KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  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 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. StretchableObjectResizer::StretchableObjectResizer() {}
  21. StretchableObjectResizer::~StretchableObjectResizer() {}
  22. void StretchableObjectResizer::addItem (const double size,
  23. const double minSize, const double maxSize,
  24. const int order)
  25. {
  26. // the order must be >= 0 but less than the maximum integer value.
  27. jassert (order >= 0 && order < std::numeric_limits<int>::max());
  28. jassert (maxSize >= minSize);
  29. Item item;
  30. item.size = size;
  31. item.minSize = minSize;
  32. item.maxSize = maxSize;
  33. item.order = order;
  34. items.add (item);
  35. }
  36. double StretchableObjectResizer::getItemSize (const int index) const noexcept
  37. {
  38. return isPositiveAndBelow (index, items.size()) ? items.getReference (index).size
  39. : 0.0;
  40. }
  41. void StretchableObjectResizer::resizeToFit (const double targetSize)
  42. {
  43. int order = 0;
  44. for (;;)
  45. {
  46. double currentSize = 0;
  47. double minSize = 0;
  48. double maxSize = 0;
  49. int nextHighestOrder = std::numeric_limits<int>::max();
  50. for (int i = 0; i < items.size(); ++i)
  51. {
  52. const Item& it = items.getReference (i);
  53. currentSize += it.size;
  54. if (it.order <= order)
  55. {
  56. minSize += it.minSize;
  57. maxSize += it.maxSize;
  58. }
  59. else
  60. {
  61. minSize += it.size;
  62. maxSize += it.size;
  63. nextHighestOrder = jmin (nextHighestOrder, it.order);
  64. }
  65. }
  66. const double thisIterationTarget = jlimit (minSize, maxSize, targetSize);
  67. if (thisIterationTarget >= currentSize)
  68. {
  69. const double availableExtraSpace = maxSize - currentSize;
  70. const double targetAmountOfExtraSpace = thisIterationTarget - currentSize;
  71. const double scale = availableExtraSpace > 0 ? targetAmountOfExtraSpace / availableExtraSpace : 1.0;
  72. for (int i = 0; i < items.size(); ++i)
  73. {
  74. Item& it = items.getReference (i);
  75. if (it.order <= order)
  76. it.size = jlimit (it.minSize, it.maxSize, it.size + (it.maxSize - it.size) * scale);
  77. }
  78. }
  79. else
  80. {
  81. const double amountOfSlack = currentSize - minSize;
  82. const double targetAmountOfSlack = thisIterationTarget - minSize;
  83. const double scale = targetAmountOfSlack / amountOfSlack;
  84. for (int i = 0; i < items.size(); ++i)
  85. {
  86. Item& it = items.getReference (i);
  87. if (it.order <= order)
  88. it.size = jmax (it.minSize, it.minSize + (it.size - it.minSize) * scale);
  89. }
  90. }
  91. if (nextHighestOrder < std::numeric_limits<int>::max())
  92. order = nextHighestOrder;
  93. else
  94. break;
  95. }
  96. }
  97. } // namespace juce