fix(view): park untagged leaves in non-Arrange modes; refresh TCP/MCP on apply
planToggle now enumerates all leaves in the FolderTree instead of only tagged membership entries, so untagged (Arrange-member) tracks park in Design and restore in Arrange. applyMode calls TrackList_AdjustWindows + UpdateArrange so changes render immediately. Correct the stale "tagged-only" invariant comments.
This commit is contained in:
@@ -383,6 +383,92 @@ static void testPlanToggleParkHasEmptyFxOffline() {
|
||||
CHECK(plan.park[0].flags.size() == 4);
|
||||
}
|
||||
|
||||
// -- 7b. Untagged leaves are managed by the mode system ----------------------
|
||||
//
|
||||
// The core semantic fix: an untagged leaf is an Arrange member. planToggle must
|
||||
// enumerate EVERY leaf in the tree (not just membership_.all()), so an untagged
|
||||
// leaf — absent from the membership index — parks in every non-Arrange mode and
|
||||
// restores in Arrange, identically to a tagged leaf. Parents and show-both leaves
|
||||
// remain never-parked. Tagged-leaf behavior is unchanged.
|
||||
|
||||
static void testUntaggedLeavesManagedByModeSystem() {
|
||||
ViewModeModel vm;
|
||||
|
||||
// A tree of leaves NONE of which are in the membership index (all untagged),
|
||||
// plus a parent folder and a show-both leaf to prove they stay untouched.
|
||||
FolderTree tree;
|
||||
tree.nodes.push_back(FolderNode{"{P}", "", /*isParent=*/true});
|
||||
tree.nodes.push_back(FolderNode{"{U1}", "{P}", false}); // untagged leaf
|
||||
tree.nodes.push_back(FolderNode{"{U2}", "{P}", false}); // untagged leaf
|
||||
tree.nodes.push_back(FolderNode{"{SB}", "", false}); // show-both leaf
|
||||
vm.membership().setShowBoth("{SB}", true);
|
||||
|
||||
// (iii) Enumeration covers leaves absent from the membership index: {U1}/{U2}
|
||||
// are NOT in membership_.all(), yet the planner reaches them.
|
||||
CHECK(vm.membership().query("{U1}") == nullptr);
|
||||
CHECK(vm.membership().query("{U2}") == nullptr);
|
||||
|
||||
// (i) Toggling to Design (non-Arrange): every untagged leaf is parked.
|
||||
auto toDesign = vm.planToggle(tree, kDesignModeId);
|
||||
CHECK(parkTargets(toDesign, "{U1}"));
|
||||
CHECK(parkTargets(toDesign, "{U2}"));
|
||||
|
||||
// (iv) The parent and the show-both leaf are NEVER parked, in either mode.
|
||||
CHECK(!parkTargets(toDesign, "{P}"));
|
||||
CHECK(!parkTargets(toDesign, "{SB}"));
|
||||
|
||||
// (ii) Toggling to Arrange: the untagged leaves are Arrange members ⇒ active and
|
||||
// NOT parked. (No snapshot stored yet ⇒ no restore op either; just not parked.)
|
||||
auto toArrange = vm.planToggle(tree, kArrangeModeId);
|
||||
CHECK(!parkTargets(toArrange, "{U1}"));
|
||||
CHECK(!parkTargets(toArrange, "{U2}"));
|
||||
CHECK(restoreFor(toArrange, "{U1}") == nullptr);
|
||||
CHECK(!parkTargets(toArrange, "{P}"));
|
||||
CHECK(!parkTargets(toArrange, "{SB}"));
|
||||
|
||||
// (vi) Restore-from-snapshot fidelity for a previously-parked UNTAGGED leaf:
|
||||
// an untagged leaf parked while in Design carries a snapshot; toggling back to
|
||||
// Arrange restores it from that snapshot verbatim, never a hardcoded default.
|
||||
TrackSnapshot snap;
|
||||
snap.showInTcp = 1; snap.showInMixer = 1; snap.mainSend = 0; snap.fxEnable = 1;
|
||||
snap.fxOffline = {0, 1};
|
||||
vm.storeSnapshot("{U1}", snap); // as the shell would, before parking it in Design
|
||||
auto backToArrange = vm.planToggle(tree, kArrangeModeId);
|
||||
const TrackPlan* r = restoreFor(backToArrange, "{U1}");
|
||||
CHECK(r != nullptr);
|
||||
if (r) {
|
||||
CHECK(flagValue(*r, Flag::ShowInTcp) == 1);
|
||||
CHECK(flagValue(*r, Flag::ShowInMixer) == 1);
|
||||
CHECK(flagValue(*r, Flag::MainSend) == 0); // captured 0 comes back 0
|
||||
CHECK(flagValue(*r, Flag::FxEnable) == 1);
|
||||
CHECK(r->fxOffline.size() == 2);
|
||||
CHECK(r->fxOffline[0].offline == false);
|
||||
CHECK(r->fxOffline[1].offline == true);
|
||||
}
|
||||
}
|
||||
|
||||
// (v) Tagged-leaf park/restore behavior is unchanged after the untagged fix: a leaf
|
||||
// tagged Design parks in Arrange and is active (not parked) in Design, and a mix of
|
||||
// tagged + untagged leaves each land on the correct side of the toggle.
|
||||
|
||||
static void testTaggedLeafBehaviorUnchangedWithUntagged() {
|
||||
ViewModeModel vm;
|
||||
FolderTree tree;
|
||||
tree.nodes.push_back(FolderNode{"{DES}", "", false}); // tagged into Design
|
||||
tree.nodes.push_back(FolderNode{"{UNT}", "", false}); // untagged ⇒ Arrange
|
||||
vm.membership().tag("{DES}", kDesignModeId);
|
||||
|
||||
// In Design: {DES} active (not parked); {UNT} inactive ⇒ parked.
|
||||
auto design = vm.planToggle(tree, kDesignModeId);
|
||||
CHECK(!parkTargets(design, "{DES}"));
|
||||
CHECK(parkTargets(design, "{UNT}"));
|
||||
|
||||
// In Arrange: {DES} inactive ⇒ parked; {UNT} active (not parked).
|
||||
auto arrange = vm.planToggle(tree, kArrangeModeId);
|
||||
CHECK(parkTargets(arrange, "{DES}"));
|
||||
CHECK(!parkTargets(arrange, "{UNT}"));
|
||||
}
|
||||
|
||||
// -- 8. nextModeId cycle (D4 toggle helper) ----------------------------------
|
||||
|
||||
static void testNextModeIdCycles() {
|
||||
@@ -417,6 +503,8 @@ int main() {
|
||||
testEmptyModelRoundTrip();
|
||||
testMalformedJson();
|
||||
testPlanToggleParkHasEmptyFxOffline();
|
||||
testUntaggedLeavesManagedByModeSystem();
|
||||
testTaggedLeafBehaviorUnchangedWithUntagged();
|
||||
testNextModeIdCycles();
|
||||
|
||||
if (g_fail == 0) std::printf("All tests passed.\n");
|
||||
|
||||
Reference in New Issue
Block a user