Skip to content

Commit 0801f4a

Browse files
committed
More work
1 parent 226a384 commit 0801f4a

File tree

3 files changed

+386
-84
lines changed

3 files changed

+386
-84
lines changed

modules/yup_data_model/tree/yup_DataTree.cpp

Lines changed: 115 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,17 @@ class AddChildAction : public UndoableAction
182182

183183
if (state == UndoableActionState::Redo)
184184
{
185-
// Remove from previous parent if any
186-
if (auto oldParentObj = childTree.object->parent.lock())
185+
// Capture the child's current parent (if any) for undo
186+
if (auto currentParent = childTree.object->parent.lock())
187187
{
188-
DataTree oldParent (oldParentObj);
189-
oldParent.removeChild (childTree);
188+
previousParent = DataTree (currentParent);
189+
previousIndex = previousParent.indexOf (childTree);
190+
previousParent.removeChild (childTree);
191+
}
192+
else
193+
{
194+
previousParent = DataTree(); // No previous parent
195+
previousIndex = -1;
190196
}
191197

192198
const int numChildren = static_cast<int> (parentTree.object->children.size());
@@ -203,8 +209,24 @@ class AddChildAction : public UndoableAction
203209
if (childIndex >= 0)
204210
{
205211
parentTree.object->children.erase (parentTree.object->children.begin() + childIndex);
206-
childTree.object->parent.reset();
207212
parentTree.object->sendChildRemovedMessage (childTree, childIndex);
213+
214+
// Restore previous parent
215+
if (previousParent.isValid())
216+
{
217+
// Restore to previous parent at previous index
218+
const int numChildren = static_cast<int> (previousParent.object->children.size());
219+
const int actualIndex = (previousIndex < 0 || previousIndex > numChildren) ? numChildren : previousIndex;
220+
221+
previousParent.object->children.insert (previousParent.object->children.begin() + actualIndex, childTree);
222+
childTree.object->parent = previousParent.object;
223+
previousParent.object->sendChildAddedMessage (childTree);
224+
}
225+
else
226+
{
227+
// No previous parent - clear parent reference
228+
childTree.object->parent.reset();
229+
}
208230
}
209231
}
210232

@@ -215,6 +237,8 @@ class AddChildAction : public UndoableAction
215237
DataTree parentTree;
216238
DataTree childTree;
217239
int index;
240+
DataTree previousParent; // For undo: the child's parent before this action
241+
int previousIndex = -1; // For undo: the child's index in previous parent
218242
};
219243

220244
class RemoveChildAction : public UndoableAction
@@ -367,17 +391,21 @@ class MoveChildAction : public UndoableAction
367391

368392
//==============================================================================
369393

370-
class TransactionAction : public UndoableAction
394+
class SimpleTransactionAction : public UndoableAction
371395
{
372396
public:
373-
TransactionAction (DataTree tree, const String& desc, const NamedValueSet& origProps, const std::vector<DataTree>& origChildren, const std::vector<DataTree::Transaction::PropertyChange>& propChanges, const std::vector<DataTree::Transaction::ChildChange>& childChanges)
397+
SimpleTransactionAction (DataTree tree, const String& desc, const NamedValueSet& origProps, const std::vector<DataTree>& origChildren)
374398
: dataTree (tree)
375399
, description (desc)
376400
, originalProperties (origProps)
377401
, originalChildren (origChildren)
378-
, propertyChanges (propChanges)
379-
, childChangeList (childChanges)
380402
{
403+
// Capture current state as the "after" state
404+
if (dataTree.object != nullptr)
405+
{
406+
currentProperties = dataTree.object->properties;
407+
currentChildren = dataTree.object->children;
408+
}
381409
}
382410

383411
bool isValid() const override
@@ -392,62 +420,63 @@ class TransactionAction : public UndoableAction
392420

393421
if (state == UndoableActionState::Redo)
394422
{
395-
// Reapply all the changes
396-
applyChangesToTree();
397-
return true;
423+
// Restore "after" state (current/new state)
424+
restoreState (currentProperties, currentChildren);
398425
}
399426
else // Undo
400427
{
401-
// Restore original state
402-
dataTree.object->properties = originalProperties;
403-
dataTree.object->children = originalChildren;
404-
405-
// Update parent pointers for children
406-
for (auto& child : dataTree.object->children)
407-
{
408-
if (child.object != nullptr)
409-
child.object->parent = dataTree.object;
410-
}
411-
412-
// Send notifications for all properties
413-
for (int i = 0; i < originalProperties.size(); ++i)
414-
dataTree.object->sendPropertyChangeMessage (originalProperties.getName (i));
415-
416-
// Send notifications for children
417-
for (size_t i = 0; i < originalChildren.size(); ++i)
418-
dataTree.object->sendChildAddedMessage (originalChildren[i]);
419-
420-
return true;
428+
// Restore "before" state (original state)
429+
restoreState (originalProperties, originalChildren);
421430
}
431+
432+
return true;
422433
}
423434

424435
private:
425-
void applyChangesToTree()
436+
void restoreState (const NamedValueSet& props, const std::vector<DataTree>& children)
426437
{
427-
if (dataTree.object == nullptr)
428-
return;
429-
430-
// Start with original state
431-
dataTree.object->properties = originalProperties;
432-
dataTree.object->children = originalChildren;
438+
// Clear parent references for children that will be removed
439+
for (const auto& currentChild : dataTree.object->children)
440+
{
441+
bool willBeKept = false;
442+
for (const auto& newChild : children)
443+
{
444+
if (currentChild.object == newChild.object)
445+
{
446+
willBeKept = true;
447+
break;
448+
}
449+
}
450+
451+
if (!willBeKept && currentChild.object != nullptr)
452+
{
453+
currentChild.object->parent.reset();
454+
}
455+
}
456+
457+
// Restore properties and children
458+
dataTree.object->properties = props;
459+
dataTree.object->children = children;
433460

434-
// Update parent pointers for original children
435-
for (auto& child : dataTree.object->children)
461+
// Set parent references for restored children
462+
for (const auto& child : dataTree.object->children)
436463
{
437464
if (child.object != nullptr)
438465
child.object->parent = dataTree.object;
439466
}
440467

441-
// Apply all changes using the shared implementation
442-
DataTree::Transaction::applyChangesToTree (dataTree, originalProperties, originalChildren, propertyChanges, childChangeList);
468+
// Send notifications
469+
for (int i = 0; i < props.size(); ++i)
470+
dataTree.object->sendPropertyChangeMessage (props.getName (i));
471+
472+
for (size_t i = 0; i < children.size(); ++i)
473+
dataTree.object->sendChildAddedMessage (children[i]);
443474
}
444475

445476
DataTree dataTree;
446477
String description;
447-
NamedValueSet originalProperties;
448-
std::vector<DataTree> originalChildren;
449-
std::vector<DataTree::Transaction::PropertyChange> propertyChanges;
450-
std::vector<DataTree::Transaction::ChildChange> childChangeList;
478+
NamedValueSet originalProperties, currentProperties;
479+
std::vector<DataTree> originalChildren, currentChildren;
451480
};
452481

453482
//==============================================================================
@@ -523,6 +552,40 @@ DataTree::DataTree (const Identifier& type)
523552
{
524553
}
525554

555+
DataTree::DataTree (const Identifier& type,
556+
const std::initializer_list<std::pair<Identifier, var>>& properties)
557+
: DataTree (type)
558+
{
559+
auto transaction = beginTransaction();
560+
561+
for (const auto& [key, value] : properties)
562+
transaction.setProperty (key, value);
563+
}
564+
565+
DataTree::DataTree (const Identifier& type,
566+
const std::initializer_list<DataTree>& children)
567+
: DataTree (type)
568+
{
569+
auto transaction = beginTransaction();
570+
571+
for (const auto& child : children)
572+
transaction.addChild (child);
573+
}
574+
575+
DataTree::DataTree (const Identifier& type,
576+
const std::initializer_list<std::pair<Identifier, var>>& properties,
577+
const std::initializer_list<DataTree>& children)
578+
: DataTree (type)
579+
{
580+
auto transaction = beginTransaction();
581+
582+
for (const auto& [key, value] : properties)
583+
transaction.setProperty (key, value);
584+
585+
for (const auto& child : children)
586+
transaction.addChild (child);
587+
}
588+
526589
DataTree::DataTree (const DataTree& other) noexcept
527590
: object (other.object)
528591
{
@@ -1240,8 +1303,11 @@ void DataTree::Transaction::commit()
12401303

12411304
if (undoManager != nullptr && (! propertyChanges.empty() || ! childChanges.empty()))
12421305
{
1243-
// Use undo manager to perform the transaction action
1244-
undoManager->perform (new TransactionAction (dataTree, description, originalProperties, originalChildren, propertyChanges, childChanges));
1306+
// Apply changes first to get final state, then create undo action with before/after states
1307+
applyChangesToTree (dataTree, originalProperties, originalChildren, propertyChanges, childChanges);
1308+
1309+
// Create a simple action that can restore the original state
1310+
undoManager->perform (new SimpleTransactionAction (dataTree, description, originalProperties, originalChildren));
12451311
}
12461312
else
12471313
{

modules/yup_data_model/tree/yup_DataTree.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,16 @@ class YUP_API DataTree
116116
*/
117117
explicit DataTree (const Identifier& type);
118118

119+
DataTree (const Identifier& type,
120+
const std::initializer_list<std::pair<Identifier, var>>& properties);
121+
122+
DataTree (const Identifier& type,
123+
const std::initializer_list<DataTree>& children);
124+
125+
DataTree (const Identifier& type,
126+
const std::initializer_list<std::pair<Identifier, var>>& properties,
127+
const std::initializer_list<DataTree>& children);
128+
119129
/**
120130
Copy constructor - creates a shallow copy that shares the same internal data.
121131
@@ -1221,7 +1231,7 @@ class YUP_API DataTree
12211231
friend class RemoveChildAction;
12221232
friend class RemoveAllChildrenAction;
12231233
friend class MoveChildAction;
1224-
friend class TransactionAction;
1234+
friend class SimpleTransactionAction;
12251235

12261236
class DataObject : public std::enable_shared_from_this<DataObject>
12271237
{

0 commit comments

Comments
 (0)