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.

138 lines
3.6KB

  1. #pragma once
  2. #include "ui/common.hpp"
  3. #include "math.hpp"
  4. #include "string.hpp"
  5. namespace rack {
  6. /** A controller for manipulating a float value (which subclasses must store somehow) with limits and labels
  7. Often used as a decorator component for Widgets that read or write a quantity.
  8. */
  9. struct Quantity {
  10. virtual ~Quantity() {}
  11. /** Sets the value directly
  12. Override this to change the state of your subclass to represent the new value.
  13. */
  14. virtual void setValue(float value) {}
  15. /** Returns the value
  16. Override this to return the state of your subclass.
  17. */
  18. virtual float getValue() {return 0.f;}
  19. /** Returns the minimum allowed value */
  20. virtual float getMinValue() {return 0.f;}
  21. /** Returns the maximum allowed value */
  22. virtual float getMaxValue() {return 1.f;}
  23. /** Returns the default value, for resetting */
  24. virtual float getDefaultValue() {return 0.f;}
  25. /** Returns the value, possibly transformed for displaying
  26. Useful for logarithmic scaling, multiplying by 100 for percentages, etc.
  27. */
  28. virtual float getDisplayValue() {return getValue();}
  29. /** Inversely transforms the display value and sets the value */
  30. virtual void setDisplayValue(float displayValue) {setValue(displayValue);}
  31. /** The number of decimal places for displaying
  32. A precision of 2 will display as "1.00" for example.
  33. */
  34. virtual int getDisplayPrecision() {return 2;}
  35. /** Returns a string representation of the display value */
  36. virtual std::string getDisplayValueString() {
  37. return string::f("%.*f", getDisplayPrecision(), getDisplayValue());
  38. }
  39. virtual void setDisplayValueString(std::string s) {
  40. float displayValue = 0.f;
  41. int n = std::sscanf(s.c_str(), "%f", &displayValue);
  42. if (n == 1)
  43. setDisplayValue(displayValue);
  44. }
  45. /** The name of the quantity */
  46. virtual std::string getLabel() {return "";}
  47. /** The unit abbreviation of the quantity
  48. Include an initial space character if you want a space after the number, e.g. "440 Hz". This allows space-less units, like "100%".
  49. */
  50. virtual std::string getUnit() {return "";}
  51. /** Returns a string representation of the quantity */
  52. virtual std::string getString() {
  53. std::string s;
  54. std::string label = getLabel();
  55. if (!label.empty())
  56. s += label + ": ";
  57. s += getDisplayValueString() + getUnit();
  58. return s;
  59. }
  60. // Helper methods
  61. /** Resets the value to the default value */
  62. void reset() {
  63. setValue(getDefaultValue());
  64. }
  65. /** Checks whether the value is at the min value */
  66. bool isMin() {
  67. return getValue() <= getMinValue();
  68. }
  69. /** Checks whether the value is at the max value */
  70. bool isMax() {
  71. return getValue() >= getMaxValue();
  72. }
  73. /** Sets the value to the min value */
  74. void setMin() {
  75. setValue(getMinValue());
  76. }
  77. /** Sets the value to the max value */
  78. void setMax() {
  79. setValue(getMaxValue());
  80. }
  81. /** Sets value from the range 0 to 1 */
  82. void setScaledValue(float scaledValue) {
  83. setValue(math::rescale(scaledValue, 0.f, 1.f, getMinValue(), getMaxValue()));
  84. }
  85. /** Returns the value rescaled to the range 0 to 1 */
  86. float getScaledValue() {
  87. return math::rescale(getValue(), getMinValue(), getMaxValue(), 0.f, 1.f);
  88. }
  89. /** The difference between the max and min values */
  90. float getRange() {
  91. return getMaxValue() - getMinValue();
  92. }
  93. /** Checks whether the bounds are finite */
  94. bool isBounded() {
  95. return std::isfinite(getMinValue()) && std::isfinite(getMaxValue());
  96. }
  97. /** Adds an amount to the value */
  98. void moveValue(float deltaValue) {
  99. setValue(getValue() + deltaValue);
  100. }
  101. /** Adds an amount to the value scaled to the range 0 to 1 */
  102. void moveScaledValue(float deltaScaledValue) {
  103. moveValue(deltaScaledValue * getRange());
  104. }
  105. };
  106. } // namespace rack