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.

235 lines
5.3KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE 6 technical preview.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. You may use this code under the terms of the GPL v3
  6. (see www.gnu.org/licenses).
  7. For this technical preview, this file is not subject to commercial licensing.
  8. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  9. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  10. DISCLAIMED.
  11. ==============================================================================
  12. */
  13. namespace juce
  14. {
  15. Value::ValueSource::ValueSource()
  16. {
  17. }
  18. Value::ValueSource::~ValueSource()
  19. {
  20. cancelPendingUpdate();
  21. }
  22. void Value::ValueSource::handleAsyncUpdate()
  23. {
  24. sendChangeMessage (true);
  25. }
  26. void Value::ValueSource::sendChangeMessage (const bool synchronous)
  27. {
  28. const int numListeners = valuesWithListeners.size();
  29. if (numListeners > 0)
  30. {
  31. if (synchronous)
  32. {
  33. const ReferenceCountedObjectPtr<ValueSource> localRef (this);
  34. cancelPendingUpdate();
  35. for (int i = numListeners; --i >= 0;)
  36. if (Value* const v = valuesWithListeners[i])
  37. v->callListeners();
  38. }
  39. else
  40. {
  41. triggerAsyncUpdate();
  42. }
  43. }
  44. }
  45. //==============================================================================
  46. class SimpleValueSource : public Value::ValueSource
  47. {
  48. public:
  49. SimpleValueSource()
  50. {
  51. }
  52. SimpleValueSource (const var& initialValue)
  53. : value (initialValue)
  54. {
  55. }
  56. var getValue() const override
  57. {
  58. return value;
  59. }
  60. void setValue (const var& newValue) override
  61. {
  62. if (! newValue.equalsWithSameType (value))
  63. {
  64. value = newValue;
  65. sendChangeMessage (false);
  66. }
  67. }
  68. private:
  69. var value;
  70. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SimpleValueSource)
  71. };
  72. //==============================================================================
  73. Value::Value() : value (new SimpleValueSource())
  74. {
  75. }
  76. Value::Value (ValueSource* const v) : value (v)
  77. {
  78. jassert (v != nullptr);
  79. }
  80. Value::Value (const var& initialValue) : value (new SimpleValueSource (initialValue))
  81. {
  82. }
  83. Value::Value (const Value& other) : value (other.value)
  84. {
  85. }
  86. Value::Value (Value&& other) noexcept
  87. {
  88. // moving a Value with listeners will lose those listeners, which
  89. // probably isn't what you wanted to happen!
  90. jassert (other.listeners.size() == 0);
  91. other.removeFromListenerList();
  92. value = std::move (other.value);
  93. }
  94. Value& Value::operator= (Value&& other) noexcept
  95. {
  96. // moving a Value with listeners will lose those listeners, which
  97. // probably isn't what you wanted to happen!
  98. jassert (other.listeners.size() == 0);
  99. other.removeFromListenerList();
  100. value = std::move (other.value);
  101. return *this;
  102. }
  103. Value::~Value()
  104. {
  105. removeFromListenerList();
  106. }
  107. void Value::removeFromListenerList()
  108. {
  109. if (listeners.size() > 0 && value != nullptr) // may be nullptr after a move operation
  110. value->valuesWithListeners.removeValue (this);
  111. }
  112. //==============================================================================
  113. var Value::getValue() const
  114. {
  115. return value->getValue();
  116. }
  117. Value::operator var() const
  118. {
  119. return value->getValue();
  120. }
  121. void Value::setValue (const var& newValue)
  122. {
  123. value->setValue (newValue);
  124. }
  125. String Value::toString() const
  126. {
  127. return value->getValue().toString();
  128. }
  129. Value& Value::operator= (const var& newValue)
  130. {
  131. value->setValue (newValue);
  132. return *this;
  133. }
  134. void Value::referTo (const Value& valueToReferTo)
  135. {
  136. if (valueToReferTo.value != value)
  137. {
  138. if (listeners.size() > 0)
  139. {
  140. value->valuesWithListeners.removeValue (this);
  141. valueToReferTo.value->valuesWithListeners.add (this);
  142. }
  143. value = valueToReferTo.value;
  144. callListeners();
  145. }
  146. }
  147. bool Value::refersToSameSourceAs (const Value& other) const
  148. {
  149. return value == other.value;
  150. }
  151. bool Value::operator== (const Value& other) const
  152. {
  153. return value == other.value || value->getValue() == other.getValue();
  154. }
  155. bool Value::operator!= (const Value& other) const
  156. {
  157. return value != other.value && value->getValue() != other.getValue();
  158. }
  159. //==============================================================================
  160. void Value::addListener (Value::Listener* listener)
  161. {
  162. if (listener != nullptr)
  163. {
  164. if (listeners.size() == 0)
  165. value->valuesWithListeners.add (this);
  166. listeners.add (listener);
  167. }
  168. }
  169. void Value::removeListener (Value::Listener* listener)
  170. {
  171. listeners.remove (listener);
  172. if (listeners.size() == 0)
  173. value->valuesWithListeners.removeValue (this);
  174. }
  175. void Value::callListeners()
  176. {
  177. if (listeners.size() > 0)
  178. {
  179. Value v (*this); // (create a copy in case this gets deleted by a callback)
  180. listeners.call ([&] (Value::Listener& l) { l.valueChanged (v); });
  181. }
  182. }
  183. OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const Value& value)
  184. {
  185. return stream << value.toString();
  186. }
  187. } // namespace juce