1 /* 2 ============================================================================== 3 4 This file is part of the JUCE library. 5 Copyright (c) 2017 - ROLI Ltd. 6 7 JUCE is an open source library subject to commercial or open-source 8 licensing. 9 10 By using JUCE, you agree to the terms of both the JUCE 5 End-User License 11 Agreement and JUCE 5 Privacy Policy (both updated and effective as of the 12 27th April 2017). 13 14 End User License Agreement: www.juce.com/juce-5-licence 15 Privacy Policy: www.juce.com/juce-5-privacy-policy 16 17 Or: You may also use this code under the terms of the GPL v3 (see 18 www.gnu.org/licenses). 19 20 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER 21 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE 22 DISCLAIMED. 23 24 ============================================================================== 25 */ 26 27 namespace juce 28 { 29 ValueSource()30Value::ValueSource::ValueSource() 31 { 32 } 33 ~ValueSource()34Value::ValueSource::~ValueSource() 35 { 36 cancelPendingUpdate(); 37 } 38 handleAsyncUpdate()39void Value::ValueSource::handleAsyncUpdate() 40 { 41 sendChangeMessage (true); 42 } 43 sendChangeMessage(const bool synchronous)44void Value::ValueSource::sendChangeMessage (const bool synchronous) 45 { 46 const int numListeners = valuesWithListeners.size(); 47 48 if (numListeners > 0) 49 { 50 if (synchronous) 51 { 52 const ReferenceCountedObjectPtr<ValueSource> localRef (this); 53 54 cancelPendingUpdate(); 55 56 for (int i = numListeners; --i >= 0;) 57 if (Value* const v = valuesWithListeners[i]) 58 v->callListeners(); 59 } 60 else 61 { 62 triggerAsyncUpdate(); 63 } 64 } 65 } 66 67 //============================================================================== 68 class SimpleValueSource : public Value::ValueSource 69 { 70 public: SimpleValueSource()71 SimpleValueSource() 72 { 73 } 74 SimpleValueSource(const var & initialValue)75 SimpleValueSource (const var& initialValue) 76 : value (initialValue) 77 { 78 } 79 getValue() const80 var getValue() const override 81 { 82 return value; 83 } 84 setValue(const var & newValue)85 void setValue (const var& newValue) override 86 { 87 if (! newValue.equalsWithSameType (value)) 88 { 89 value = newValue; 90 sendChangeMessage (false); 91 } 92 } 93 94 private: 95 var value; 96 97 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SimpleValueSource) 98 }; 99 100 101 //============================================================================== Value()102Value::Value() : value (new SimpleValueSource()) 103 { 104 } 105 Value(ValueSource * const v)106Value::Value (ValueSource* const v) : value (v) 107 { 108 jassert (v != nullptr); 109 } 110 Value(const var & initialValue)111Value::Value (const var& initialValue) : value (new SimpleValueSource (initialValue)) 112 { 113 } 114 Value(const Value & other)115Value::Value (const Value& other) : value (other.value) 116 { 117 } 118 Value(Value && other)119Value::Value (Value&& other) noexcept 120 { 121 // moving a Value with listeners will lose those listeners, which 122 // probably isn't what you wanted to happen! 123 jassert (other.listeners.size() == 0); 124 125 other.removeFromListenerList(); 126 value = std::move (other.value); 127 } 128 operator =(Value && other)129Value& Value::operator= (Value&& other) noexcept 130 { 131 // moving a Value with listeners will lose those listeners, which 132 // probably isn't what you wanted to happen! 133 jassert (other.listeners.size() == 0); 134 135 other.removeFromListenerList(); 136 value = std::move (other.value); 137 return *this; 138 } 139 ~Value()140Value::~Value() 141 { 142 removeFromListenerList(); 143 } 144 removeFromListenerList()145void Value::removeFromListenerList() 146 { 147 if (listeners.size() > 0 && value != nullptr) // may be nullptr after a move operation 148 value->valuesWithListeners.removeValue (this); 149 } 150 151 //============================================================================== getValue() const152var Value::getValue() const 153 { 154 return value->getValue(); 155 } 156 operator var() const157Value::operator var() const 158 { 159 return value->getValue(); 160 } 161 setValue(const var & newValue)162void Value::setValue (const var& newValue) 163 { 164 value->setValue (newValue); 165 } 166 toString() const167String Value::toString() const 168 { 169 return value->getValue().toString(); 170 } 171 operator =(const var & newValue)172Value& Value::operator= (const var& newValue) 173 { 174 value->setValue (newValue); 175 return *this; 176 } 177 referTo(const Value & valueToReferTo)178void Value::referTo (const Value& valueToReferTo) 179 { 180 if (valueToReferTo.value != value) 181 { 182 if (listeners.size() > 0) 183 { 184 value->valuesWithListeners.removeValue (this); 185 valueToReferTo.value->valuesWithListeners.add (this); 186 } 187 188 value = valueToReferTo.value; 189 callListeners(); 190 } 191 } 192 refersToSameSourceAs(const Value & other) const193bool Value::refersToSameSourceAs (const Value& other) const 194 { 195 return value == other.value; 196 } 197 operator ==(const Value & other) const198bool Value::operator== (const Value& other) const 199 { 200 return value == other.value || value->getValue() == other.getValue(); 201 } 202 operator !=(const Value & other) const203bool Value::operator!= (const Value& other) const 204 { 205 return value != other.value && value->getValue() != other.getValue(); 206 } 207 208 //============================================================================== addListener(Value::Listener * listener)209void Value::addListener (Value::Listener* listener) 210 { 211 if (listener != nullptr) 212 { 213 if (listeners.size() == 0) 214 value->valuesWithListeners.add (this); 215 216 listeners.add (listener); 217 } 218 } 219 removeListener(Value::Listener * listener)220void Value::removeListener (Value::Listener* listener) 221 { 222 listeners.remove (listener); 223 224 if (listeners.size() == 0) 225 value->valuesWithListeners.removeValue (this); 226 } 227 callListeners()228void Value::callListeners() 229 { 230 if (listeners.size() > 0) 231 { 232 Value v (*this); // (create a copy in case this gets deleted by a callback) 233 listeners.call ([&] (Value::Listener& l) { l.valueChanged (v); }); 234 } 235 } 236 operator <<(OutputStream & stream,const Value & value)237OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const Value& value) 238 { 239 return stream << value.toString(); 240 } 241 242 } // namespace juce 243