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.

119 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. StretchableObjectResizer::StretchableObjectResizer() {}
  20. StretchableObjectResizer::~StretchableObjectResizer() {}
  21. void StretchableObjectResizer::addItem (const double size,
  22. const double minSize, const double maxSize,
  23. const int order)
  24. {
  25. // the order must be >= 0 but less than the maximum integer value.
  26. jassert (order >= 0 && order < std::numeric_limits<int>::max());
  27. jassert (maxSize >= minSize);
  28. Item item;
  29. item.size = size;
  30. item.minSize = minSize;
  31. item.maxSize = maxSize;
  32. item.order = order;
  33. items.add (item);
  34. }
  35. double StretchableObjectResizer::getItemSize (const int index) const noexcept
  36. {
  37. return isPositiveAndBelow (index, items.size()) ? items.getReference (index).size
  38. : 0.0;
  39. }
  40. void StretchableObjectResizer::resizeToFit (const double targetSize)
  41. {
  42. int order = 0;
  43. for (;;)
  44. {
  45. double currentSize = 0;
  46. double minSize = 0;
  47. double maxSize = 0;
  48. int nextHighestOrder = std::numeric_limits<int>::max();
  49. for (int i = 0; i < items.size(); ++i)
  50. {
  51. const Item& it = items.getReference(i);
  52. currentSize += it.size;
  53. if (it.order <= order)
  54. {
  55. minSize += it.minSize;
  56. maxSize += it.maxSize;
  57. }
  58. else
  59. {
  60. minSize += it.size;
  61. maxSize += it.size;
  62. nextHighestOrder = jmin (nextHighestOrder, it.order);
  63. }
  64. }
  65. const double thisIterationTarget = jlimit (minSize, maxSize, targetSize);
  66. if (thisIterationTarget >= currentSize)
  67. {
  68. const double availableExtraSpace = maxSize - currentSize;
  69. const double targetAmountOfExtraSpace = thisIterationTarget - currentSize;
  70. const double scale = availableExtraSpace > 0 ? targetAmountOfExtraSpace / availableExtraSpace : 1.0;
  71. for (int i = 0; i < items.size(); ++i)
  72. {
  73. Item& it = items.getReference(i);
  74. if (it.order <= order)
  75. it.size = jlimit (it.minSize, it.maxSize, it.size + (it.maxSize - it.size) * scale);
  76. }
  77. }
  78. else
  79. {
  80. const double amountOfSlack = currentSize - minSize;
  81. const double targetAmountOfSlack = thisIterationTarget - minSize;
  82. const double scale = targetAmountOfSlack / amountOfSlack;
  83. for (int i = 0; i < items.size(); ++i)
  84. {
  85. Item& it = items.getReference(i);
  86. if (it.order <= order)
  87. it.size = jmax (it.minSize, it.minSize + (it.size - it.minSize) * scale);
  88. }
  89. }
  90. if (nextHighestOrder < std::numeric_limits<int>::max())
  91. order = nextHighestOrder;
  92. else
  93. break;
  94. }
  95. }