cello
JUCE ValueTrees for Humans
Loading...
Searching...
No Matches
cello_object.h
1/*
2 Copyright (c) 2023 Brett g Porter
3 Permission is hereby granted, free of charge, to any person obtaining a copy
4 of this software and associated documentation files (the "Software"), to deal
5 in the Software without restriction, including without limitation the rights
6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 copies of the Software, and to permit persons to whom the Software is
8 furnished to do so, subject to the following conditions:
9 The above copyright notice and this permission notice shall be included in all
10 copies or substantial portions of the Software.
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 SOFTWARE.
18*/
19
20#pragma once
21
22#include <juce_core/juce_core.h>
23#include <juce_data_structures/juce_data_structures.h>
24
25#include "cello_update_source.h"
26
27namespace cello
28{
29class ValueBase;
30class Query;
31
32class Object : public UpdateSource,
33 public juce::ValueTree::Listener
34{
35public:
36 enum class FileFormat
37 {
38 xml, // load/store as XML text.
39 binary, // load/store in juce's binary format.
40 zipped // GZIPped juce binary.
41 };
42
43 enum class CreationType
44 {
45 initialized, // this object was default initialized when created.
46 wrapped // this object wrapped an existing tree.
47 };
48
65 Object (const juce::String& type, const Object* state);
66
74 Object (const juce::String& type, const Object& state);
75
88 Object (const juce::String& type, juce::ValueTree tree);
89
100 Object (const juce::String& type, juce::File file, FileFormat format = FileFormat::xml);
101
109 Object (const Object& rhs);
110
118 CreationType wrap (const Object& other);
119
127 Object& operator= (const Object& rhs);
128
134 ~Object () override;
135
145 bool operator== (const juce::ValueTree& rhs) const noexcept { return data == rhs; }
146
147 bool operator!= (const juce::ValueTree& rhs) const noexcept { return data != rhs; }
148
154 juce::Identifier getType () const { return data.getType (); }
155
161 juce::String getTypeName () const { return getType ().toString (); }
162
169 juce::String toXmlString (const juce::XmlElement::TextFormat& format = {}) const
170 {
171 return data.toXmlString (format);
172 }
173
185 CreationType getCreationType () const { return creationType; }
186
192 bool wasWrapped () const { return creationType == CreationType::wrapped; }
193
199 bool wasInitialized () const { return creationType == CreationType::initialized; }
200
206 operator juce::ValueTree () const { return data; }
207
214 juce::ValueTree clone (bool deep) const;
215
222 void update (const juce::MemoryBlock& updateBlock);
223
228
238 juce::ValueTree find (const cello::Query& query, bool deep = false);
239
249 juce::ValueTree findOne (const cello::Query& query, bool deep = false);
250
262 bool upsert (const Object* object, const juce::Identifier& key, bool deep = false);
263
275 void upsertAll (const Object* parent, const juce::Identifier& key, bool deep = false);
277
282
289 void setUndoManager (juce::UndoManager* undo);
290
297 juce::UndoManager* getUndoManager () const;
298
304 bool canUndo () const;
305
312 bool undo ();
313
319 bool canRedo () const;
320
327 bool redo ();
328
332 void clearUndoHistory ();
334
340
341 // An iterator to access child objects; note that it works in terms
342 // of ValueTrees, not objects (since our list of children can be
343 // heterogeneous)
344 using Iterator = juce::ValueTree::Iterator;
345 Iterator begin () { return data.begin (); }
346 Iterator end () { return data.end (); }
347
358 juce::ValueTree operator[] (int index) const;
359
365 int getNumChildren () const;
366
372 void append (Object* object);
373
380 void insert (Object* object, int index);
381
388 Object* remove (Object* object);
389
396 juce::ValueTree remove (int index);
397
404 void move (int fromIndex, int toIndex);
405
420 template <typename Comparator> void sort (Comparator& comp, bool stableSort);
421
423
429 void excludeListener (juce::ValueTree::Listener* listener) { excludedListener = listener; }
430
436 juce::ValueTree::Listener* getExcludedListener () const { return excludedListener; }
437
442
452 void onPropertyChange (juce::Identifier id, PropertyUpdateFn callback);
453
461 void onPropertyChange (PropertyUpdateFn callback) { onPropertyChange (getType (), callback); }
462
470 void onPropertyChange (const ValueBase& val, PropertyUpdateFn callback);
471
472 using ChildUpdateFn = std::function<void (juce::ValueTree& child, int oldIndex, int newIndex)>;
473
474 ChildUpdateFn onChildAdded;
475 ChildUpdateFn onChildRemoved;
476 ChildUpdateFn onChildMoved;
477
478 using SelfUpdateFn = std::function<void (void)>;
479
480 SelfUpdateFn onParentChanged;
481 SelfUpdateFn onTreeRedirected;
482
484
496
506 template <typename T> T getattr (const juce::Identifier& attr, const T& defaultVal) const
507 {
508 return juce::VariantConverter<T>::fromVar (data.getProperty (attr, defaultVal));
509 }
510
518 bool hasattr (const juce::Identifier& attr) const;
519
528 template <typename T> Object& setattr (const juce::Identifier& attr, const T& attrVal)
529 {
530 data.setProperty (attr, juce::VariantConverter<T>::toVar (attrVal), getUndoManager ());
531 return (*this);
532 }
533
538 void delattr (const juce::Identifier& attr);
539
541
547
555 static juce::ValueTree load (juce::File file, FileFormat format = FileFormat::xml);
556
564 juce::Result save (juce::File file, FileFormat format = FileFormat::xml) const;
565
567private:
577 CreationType wrap (const juce::String& type, juce::ValueTree tree);
578
592 void valueTreePropertyChanged (juce::ValueTree& treeWhosePropertyHasChanged,
593 const juce::Identifier& property) override;
594
601 void valueTreeChildAdded (juce::ValueTree& parentTree, juce::ValueTree& childTree) override;
602
610 void valueTreeChildRemoved (juce::ValueTree& parentTree, juce::ValueTree& childTree, int index) override;
611
619 void valueTreeChildOrderChanged (juce::ValueTree& childTree, int oldIndex, int newIndex) override;
620
626 void valueTreeParentChanged (juce::ValueTree& tree) override;
627
633 void valueTreeRedirected (juce::ValueTree& tree) override;
634
635protected:
637 juce::ValueTree data;
638
640 juce::UndoManager* undoManager { nullptr };
641
643 CreationType creationType { CreationType::wrapped };
644
646 juce::ValueTree::Listener* excludedListener { nullptr };
647
650 bool doForceUpdates { false };
651
652private:
659 struct PropertyUpdate
660 {
661 PropertyUpdate (juce::Identifier id_, PropertyUpdateFn fn_)
662 : id { id_ }
663 , fn { fn_ }
664 {
665 }
666
667 juce::Identifier id;
668 PropertyUpdateFn fn;
669 };
670
671 std::vector<PropertyUpdate> propertyUpdaters;
672};
673
674} // namespace cello
Definition cello_object.h:34
juce::String getTypeName() const
Get the type of this object as a string.
Definition cello_object.h:161
void move(int fromIndex, int toIndex)
Change the position of one of this object's children.
Definition cello_object.cpp:240
void setUndoManager(juce::UndoManager *undo)
Set the undo manager to use in this object (and others created from it).
Definition cello_object.cpp:139
void sort(Comparator &comp, bool stableSort)
Sort this object's children using the provided comparison object.
Definition cello_object.cpp:245
bool upsert(const Object *object, const juce::Identifier &key, bool deep=false)
Update or insert a child object (concept borrowed from MongoDB) Looks for a child with a 'key' value ...
Definition cello_object.cpp:104
void onPropertyChange(juce::Identifier id, PropertyUpdateFn callback)
Install (or clear) a function to be called when one of this Object's properties changes....
Definition cello_object.cpp:255
~Object() override
Destroy the Object object The important thing done here is to remove ourselves as a listener to the v...
Definition cello_object.cpp:74
juce::ValueTree::Listener * getExcludedListener() const
Get a pointer to the listener to exclude from property change updates.
Definition cello_object.h:436
juce::ValueTree data
The tree where our data lives.
Definition cello_object.h:637
Object & setattr(const juce::Identifier &attr, const T &attrVal)
Set a new value for the specified attribute/property. We return a reference to this object so that se...
Definition cello_object.h:528
bool operator==(const juce::ValueTree &rhs) const noexcept
test for true equivalence: does this object point to the same underlying tree as the tree on the righ...
Definition cello_object.h:145
CreationType wrap(const Object &other)
Wrap another Object's tree after this object is created.
Definition cello_object.cpp:58
bool wasInitialized() const
utility method to test the creation type as a bool.
Definition cello_object.h:199
void excludeListener(juce::ValueTree::Listener *listener)
A listener to exclude from property change updates.
Definition cello_object.h:429
Object(const juce::String &type, const Object *state)
Construct a new cello::Object object, which will attempt to initialize from the 'state' parameter....
Definition cello_object.cpp:27
juce::Result save(juce::File file, FileFormat format=FileFormat::xml) const
Save the object tree to disk.
Definition cello_object.cpp:310
void onPropertyChange(PropertyUpdateFn callback)
install or clear a generic callback that will be called when any property in the object changes....
Definition cello_object.h:461
bool redo()
Attempt to redo the last transaction.
Definition cello_object.cpp:165
bool wasWrapped() const
utility method to test the creation type as a bool.
Definition cello_object.h:192
bool hasattr(const juce::Identifier &attr) const
test the object to see if it has an attribute with this id.
Definition cello_object.cpp:275
juce::ValueTree clone(bool deep) const
Make and return a copy of our underlying value tree.
Definition cello_object.cpp:79
T getattr(const juce::Identifier &attr, const T &defaultVal) const
Get a property value from this object, or default if it doesn't have a property with that name.
Definition cello_object.h:506
bool canUndo() const
Test whether this object/tree has anything that can be undone.
Definition cello_object.cpp:144
juce::ValueTree::Listener * excludedListener
a listener to not update when properties change.
Definition cello_object.h:646
void delattr(const juce::Identifier &attr)
Remove the specified property from this object.
Definition cello_object.cpp:280
int getNumChildren() const
Check how many children this object has.
Definition cello_object.cpp:178
bool canRedo() const
Test whether this object/tree has anything that can be redone.
Definition cello_object.cpp:158
juce::UndoManager * undoManager
The undo manager to use for set() operations.
Definition cello_object.h:640
bool undo()
Attempt to undo the last transaction.
Definition cello_object.cpp:151
juce::Identifier getType() const
Get the type of this object as a juce::Identifier.
Definition cello_object.h:154
CreationType creationType
Remember how this Object was created.
Definition cello_object.h:643
juce::UndoManager * getUndoManager() const
Get the current undo manager; only useful to this object's Value objects and when creating other Obje...
Definition cello_object.cpp:250
juce::ValueTree find(const cello::Query &query, bool deep=false)
Perform a query against the children of this Object, returning a new ValueTree containing zero or mor...
Definition cello_object.cpp:94
juce::ValueTree findOne(const cello::Query &query, bool deep=false)
Perform a query against the children of this object, returning a copy of the first child found that m...
Definition cello_object.cpp:99
Object * remove(Object *object)
Attempt to remove a child object from this.
Definition cello_object.cpp:221
void clearUndoHistory()
reset the undo manager
Definition cello_object.cpp:172
void update(const juce::MemoryBlock &updateBlock)
Apply delta/update generated by the juce::ValueTreeSynchroniser class; this is used in the sync and i...
Definition cello_object.cpp:89
void append(Object *object)
Add a new child object to the end of our child object list,.
Definition cello_object.cpp:191
bool doForceUpdates
Definition cello_object.h:650
static juce::ValueTree load(juce::File file, FileFormat format=FileFormat::xml)
Reload data from disk. Used in the ctor that accepts file name and format.
Definition cello_object.cpp:285
Object & operator=(const Object &rhs)
set this object to use a different Object's value tree, which we will begin listening to....
Definition cello_object.cpp:66
juce::ValueTree operator[](int index) const
return a child tree of this object by its index. NOTE that it does not return an object; to work with...
Definition cello_object.cpp:183
CreationType getCreationType() const
Determine how this object was created, which will be one of:
Definition cello_object.h:185
void insert(Object *object, int index)
add a new child object at a specific index in the list.
Definition cello_object.cpp:196
void upsertAll(const Object *parent, const juce::Identifier &key, bool deep=false)
Perform an upsert using each of the children of the parent being passed. Common workflow here:
Definition cello_object.cpp:126
juce::String toXmlString(const juce::XmlElement::TextFormat &format={}) const
Generate a string representation of this object's tree.
Definition cello_object.h:169
Definition cello_query.h:28
Definition cello_value.h:30