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.

124 lines
3.9KB

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