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:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user