Fix parent visibility: parent visible by own membership OR derived from children

visibleTracks pass 1 now evaluates every node (parent or leaf) by its own
membership, so an untagged folder carrying its own FX/media shows in Arrange
(its default) as well as any mode derived from its children. Adds case-matrix
tests; updates the nested-Arrange assertion to the corrected rule.
This commit is contained in:
2026-07-23 06:17:34 -04:00
parent 4f1231ea81
commit 8d08279bdb
3 changed files with 134 additions and 15 deletions
+110 -2
View File
@@ -141,9 +141,13 @@ static void testParentDerivationMultiMode() {
CHECK(visibleHas(d2, "{L3}"));
CHECK(visibleHas(d2, "{F2}"));
CHECK(visibleHas(d2, "{G}"));
// In Arrange, none of the chain is visible (no Arrange leaf under it).
// In Arrange: the Design leaf {L3} stays hidden (leaf visibility unchanged), but
// the untagged parents {F2}/{G} are Arrange members by their own default, so they
// are visible in Arrange under the corrected own-membership OR derived rule.
// (See testParentOwnMembershipVisibility for the full case matrix.)
auto a2 = vm2.visibleTracks(nested, kArrangeModeId);
CHECK(!visibleHas(a2, "{L3}") && !visibleHas(a2, "{F2}") && !visibleHas(a2, "{G}"));
CHECK(!visibleHas(a2, "{L3}"));
CHECK(visibleHas(a2, "{F2}") && visibleHas(a2, "{G}"));
// A parent is NEVER parked, in either mode.
auto planD = vm.planToggle(tree, kDesignModeId);
@@ -152,6 +156,109 @@ static void testParentDerivationMultiMode() {
CHECK(!parkTargets(planA, "{F}"));
}
// -- 2b. Parent own-membership visibility (untagged folder + own FX/media) ---
//
// Corrected rule: a parent is visible in mode M if EITHER a descendant leaf is
// visible in M (existing derived rule) OR the parent belongs to M by its OWN
// membership (leafBelongsToMode on the parent's own GUID; untagged ⇒ Arrange).
// The reported case: an untagged folder whose leaves are all Design vanished in
// Arrange despite carrying its own FX/media. It must now show in Arrange (own
// default) AND Design (derived from children). Parents remain never parked.
static void testParentOwnMembershipVisibility() {
// Case A [reported]: untagged folder {F}, all leaves Design ⇒ folder visible in
// BOTH Arrange (own default) and Design (derived from children).
{
ViewModeModel vm;
FolderTree tree;
tree.nodes.push_back(FolderNode{"{F}", "", /*isParent=*/true});
tree.nodes.push_back(FolderNode{"{L1}", "{F}", false});
tree.nodes.push_back(FolderNode{"{L2}", "{F}", false});
vm.membership().tag("{L1}", kDesignModeId);
vm.membership().tag("{L2}", kDesignModeId);
// {F} itself untagged ⇒ Arrange member by default.
auto arrange = vm.visibleTracks(tree, kArrangeModeId);
auto design = vm.visibleTracks(tree, kDesignModeId);
CHECK(visibleHas(arrange, "{F}")); // own default (would FAIL under derived-only rule)
CHECK(visibleHas(design, "{F}")); // derived from Design children
// Leaves appear only in Design; neither is visible in Arrange.
CHECK(visibleHas(design, "{L1}") && visibleHas(design, "{L2}"));
CHECK(!visibleHas(arrange, "{L1}") && !visibleHas(arrange, "{L2}"));
// Still never parked, in either mode.
CHECK(!parkTargets(vm.planToggle(tree, kArrangeModeId), "{F}"));
CHECK(!parkTargets(vm.planToggle(tree, kDesignModeId), "{F}"));
}
// Case B: untagged folder, all leaves Arrange ⇒ folder visible in Arrange only.
{
ViewModeModel vm;
FolderTree tree;
tree.nodes.push_back(FolderNode{"{F}", "", true});
tree.nodes.push_back(FolderNode{"{L1}", "{F}", false}); // untagged ⇒ Arrange
tree.nodes.push_back(FolderNode{"{L2}", "{F}", false}); // untagged ⇒ Arrange
CHECK(visibleHas(vm.visibleTracks(tree, kArrangeModeId), "{F}"));
CHECK(!visibleHas(vm.visibleTracks(tree, kDesignModeId), "{F}"));
}
// Case C: untagged folder, mixed Arrange + Design leaves ⇒ visible in both.
{
ViewModeModel vm;
FolderTree tree;
tree.nodes.push_back(FolderNode{"{F}", "", true});
tree.nodes.push_back(FolderNode{"{LA}", "{F}", false}); // untagged ⇒ Arrange
tree.nodes.push_back(FolderNode{"{LD}", "{F}", false});
vm.membership().tag("{LD}", kDesignModeId);
CHECK(visibleHas(vm.visibleTracks(tree, kArrangeModeId), "{F}"));
CHECK(visibleHas(vm.visibleTracks(tree, kDesignModeId), "{F}"));
}
// Case D: nested untagged grandparent {G} > untagged parent {F} > Design leaves.
// Both intermediate folders visible in BOTH modes: own-default Arrange (they are
// untagged), and derived Design (a Design leaf lives under each).
{
ViewModeModel vm;
FolderTree tree;
tree.nodes.push_back(FolderNode{"{G}", "", true});
tree.nodes.push_back(FolderNode{"{F}", "{G}", true});
tree.nodes.push_back(FolderNode{"{L1}", "{F}", false});
tree.nodes.push_back(FolderNode{"{L2}", "{F}", false});
vm.membership().tag("{L1}", kDesignModeId);
vm.membership().tag("{L2}", kDesignModeId);
auto arrange = vm.visibleTracks(tree, kArrangeModeId);
auto design = vm.visibleTracks(tree, kDesignModeId);
CHECK(visibleHas(arrange, "{G}") && visibleHas(arrange, "{F}")); // own default
CHECK(visibleHas(design, "{G}") && visibleHas(design, "{F}")); // derived
// The Design leaves stay Design-only; not visible in Arrange.
CHECK(!visibleHas(arrange, "{L1}") && !visibleHas(arrange, "{L2}"));
}
// Case E: existing behavior unchanged — a TAGGED-Design folder holding a visible
// Design leaf still shows in Design; and a folder made visible only by a visible
// tagged-Design descendant (own membership Arrange) still derives into Design.
// Leaf visibility itself is unchanged: a Design leaf is Design-only.
{
ViewModeModel vm;
FolderTree tree;
tree.nodes.push_back(FolderNode{"{F}", "", true});
tree.nodes.push_back(FolderNode{"{LD}", "{F}", false});
vm.membership().tag("{F}", kDesignModeId); // folder tagged into Design itself
vm.membership().tag("{LD}", kDesignModeId);
auto design = vm.visibleTracks(tree, kDesignModeId);
CHECK(visibleHas(design, "{F}")); // own Design membership + derived from {LD}
CHECK(visibleHas(design, "{LD}"));
// A Design-tagged folder is NOT an Arrange member ⇒ not visible in Arrange
// unless a child is; here the only child is Design, so folder hidden in Arrange.
auto arrange = vm.visibleTracks(tree, kArrangeModeId);
CHECK(!visibleHas(arrange, "{F}"));
CHECK(!visibleHas(arrange, "{LD}")); // leaf visibility unchanged
}
}
// -- 3. Restore round-trip (the trust anchor) --------------------------------
static void testRestoreRoundTripSnapshotValues() {
@@ -638,6 +745,7 @@ static void testNestedToggleSnapshotSurvivesRepark() {
int main() {
testNModeRegistryAndMembership();
testParentDerivationMultiMode();
testParentOwnMembershipVisibility();
testRestoreRoundTripSnapshotValues();
testShowBothNeverParkedVisibleEverywhere();
testStaleGuidTolerated();