20#include "JuceHeader.h"
22#include "cello_object.h"
42 wrap (type,
static_cast<juce::ValueTree
> (tree));
45Object::Object (
const juce::String& type, juce::File file, Object::FileFormat format)
55 data.addListener (
this);
60 data.removeListener (
this);
61 const auto result {
wrap (
getType ().toString (), other) };
76 data.removeListener (
this);
81 auto cloneTree { juce::ValueTree {
getType () } };
83 cloneTree.copyPropertiesAndChildrenFrom (
data,
nullptr);
85 cloneTree.copyPropertiesFrom (
data,
nullptr);
91 juce::ValueTreeSynchroniser::applyChange (
data, updateBlock.getData (), updateBlock.getSize (),
getUndoManager ());
114 const auto val {
object->data[key] };
116 auto existingItem {
data.getChildWithProperty (key, val) };
117 if (existingItem.isValid ())
121 existingItem.copyPropertiesAndChildrenFrom (*
object,
getUndoManager ());
133 juce::ValueTree parentTree { *parent };
134 for (
const auto& child : parentTree)
136 const auto type { child.getType () };
137 Object item { type.toString (), child };
139 if (!
upsert (&item, key, deep))
152 return undoMgr->canUndo ();
159 return undoMgr->undo ();
166 return undoMgr->canRedo ();
173 return undoMgr->redo ();
180 undoMgr->clearUndoHistory ();
185 return data.getNumChildren ();
190 if (index < 0 || index >=
data.getNumChildren ())
193 return data.getChild (index);
211 juce::ValueTree newChild { *
object };
212 juce::ValueTree parent { newChild.getParent () };
214 if (parent.isValid ())
233 auto removedTree {
remove (
data.indexOf (*
object)) };
234 return removedTree.isValid () ? object :
nullptr;
239 auto treeToRemove {
data.getChild (index) };
240 if (treeToRemove.isValid ())
250template <
typename Comparator>
void Object::sort (Comparator& comp,
bool stableSort)
263 for (
auto& updater : propertyUpdaters)
265 if (updater.id ==
id)
267 updater.fn = callback;
272 propertyUpdaters.emplace_back (
id, callback);
282 return data.hasProperty (attr);
292 if (format == Object::FileFormat::xml)
294 const auto xmlText { file.loadFileAsString () };
295 return juce::ValueTree::fromXml (xmlText);
299 juce::MemoryBlock mb;
300 if (!file.loadFileAsData (mb))
305 if (format == Object::FileFormat::binary)
306 return juce::ValueTree::readFromData (mb.getData (), mb.getSize ());
307 else if (format == Object::FileFormat::zipped)
308 return juce::ValueTree::readFromGZIPData (mb.getData (), mb.getSize ());
317 if (format == FileFormat::xml)
319 auto res { file.create () };
322 if (file.replaceWithText (
data.toXmlString ()))
323 return juce::Result::ok ();
324 res = juce::Result::fail (
"Error writing to " + file.getFullPathName ());
329 juce::FileOutputStream fos { file };
330 if (!fos.openedOk ())
333 return juce::Result::fail (
"Unable to open " + file.getFullPathName () +
" for writing");
336 if (format == FileFormat::binary)
338 data.writeToStream (fos);
339 return juce::Result::ok ();
342 else if (format == FileFormat::zipped)
344 juce::GZIPCompressorOutputStream zipper { fos };
345 data.writeToStream (zipper);
346 return juce::Result::ok ();
351 return juce::Result::fail (
"Unknown file format");
354Object::CreationType
Object::wrap (
const juce::String& type, juce::ValueTree tree)
365 data.addListener (
this);
369void Object::valueTreePropertyChanged (juce::ValueTree& treeWhosePropertyHasChanged,
const juce::Identifier& property)
371 if (treeWhosePropertyHasChanged !=
data)
375 auto callUpdaterForProperty = [
this] (
const juce::Identifier& key,
const juce::Identifier& prop) ->
bool
377 for (
const auto& updater : propertyUpdaters)
379 if (updater.id == key)
381 if (updater.fn !=
nullptr)
390 if (callUpdaterForProperty (property, property))
393 callUpdaterForProperty (
getType (), property);
396void Object::valueTreeChildAdded (juce::ValueTree& parentTree, juce::ValueTree& childTree)
398 if (parentTree ==
data && onChildAdded !=
nullptr)
399 onChildAdded (childTree, -1,
data.indexOf (childTree));
402void Object::valueTreeChildRemoved (juce::ValueTree& parentTree, juce::ValueTree& childTree,
int index)
404 if (parentTree ==
data && onChildRemoved !=
nullptr)
405 onChildRemoved (childTree, index, -1);
408void Object::valueTreeChildOrderChanged (juce::ValueTree& parentTree,
int oldIndex,
int newIndex)
410 if (parentTree ==
data && onChildMoved !=
nullptr)
412 auto childTree {
data.getChild (newIndex) };
413 onChildMoved (childTree, oldIndex, newIndex);
417void Object::valueTreeParentChanged (juce::ValueTree& tree)
419 if (tree ==
data && onParentChanged !=
nullptr)
423void Object::valueTreeRedirected (juce::ValueTree& tree)
425 if (tree ==
data && onTreeRedirected !=
nullptr)
432#include "test/test_cello_object.inl"
void move(int fromIndex, int toIndex)
Change the position of one of this object's children.
Definition cello_object.cpp:245
void setUndoManager(juce::UndoManager *undo)
Set the undo manager to use in this object (and others created from it).
Definition cello_object.cpp:144
void sort(Comparator &comp, bool stableSort)
Sort this object's children using the provided comparison object.
Definition cello_object.cpp:250
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:109
~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 data
The tree where our data lives.
Definition cello_object.h:646
void onPropertyChange(const 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:260
CreationType wrap(const Object &other)
Wrap another Object's tree after this object is created.
Definition cello_object.cpp:58
int remove(const cello::Query &query)
Remove all children from the tree that match the query.
Definition cello_object.cpp:104
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:315
bool redo()
Attempt to redo the last transaction.
Definition cello_object.cpp:170
bool hasattr(const juce::Identifier &attr) const
test the object to see if it has an attribute with this id.
Definition cello_object.cpp:280
juce::ValueTree clone(bool deep) const
Make and return a copy of our underlying value tree.
Definition cello_object.cpp:79
bool canUndo() const
Test whether this object/tree has anything that can be undone.
Definition cello_object.cpp:149
void delattr(const juce::Identifier &attr)
Remove the specified property from this object.
Definition cello_object.cpp:285
int getNumChildren() const
Check how many children this object has.
Definition cello_object.cpp:183
bool canRedo() const
Test whether this object/tree has anything that can be redone.
Definition cello_object.cpp:163
juce::UndoManager * undoManager
The undo manager to use for set() operations.
Definition cello_object.h:649
bool undo()
Attempt to undo the last transaction.
Definition cello_object.cpp:156
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:652
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:255
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
operator juce::ValueTree() const
Get the ValueTree we're using as our data store.
Definition cello_object.h:206
void clearUndoHistory()
reset the undo manager
Definition cello_object.cpp:177
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:196
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:290
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:188
void insert(Object *object, int index)
add a new child object at a specific index in the list.
Definition cello_object.cpp:201
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:131
Class to navigate between subtrees that are all connected together.
Definition cello_path.h:50
@ createAll
create final tree and all intermediate trees needed to reach it.
Definition cello_path.h:67
juce::ValueTree findValueTree(juce::ValueTree &origin, SearchType searchType, juce::UndoManager *undo=nullptr)
Navigate the path from origin to a tree that is expected at the end of the current path specification...
Definition cello_path.cpp:59
@ created
performing a search created a new tree
Definition cello_path.h:74
Definition cello_query.h:28
int remove(juce::ValueTree tree) const
Remove all children from the tree that match the query.
Definition cello_query.cpp:66
juce::ValueTree search(juce::ValueTree tree, bool deep, bool returnFirstFound=false) const
Execute the query we're programmed for – iterate through the children of tree, returning a new tree o...
Definition cello_query.cpp:41
Definition cello_value.h:32
juce::Identifier getId() const
Definition cello_value.h:37