-
Notifications
You must be signed in to change notification settings - Fork 0
/
PredicateOutlineNode.m
92 lines (77 loc) · 2.11 KB
/
PredicateOutlineNode.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//
// PredicateOutlineNode.m
// SSDP Browser
//
// Created by Thomas Tempelmann on 27.02.24.
//
// Based on: https://stackoverflow.com/a/66324031/43615
//
#import "PredicateOutlineNode.h"
@interface PredicateOutlineNode()
@property NSArray *_children;
@property NSArray *_filteredChildren;
@property NSPredicate *_predicate;
@property NSInteger count;
@end
@implementation PredicateOutlineNode
- (instancetype)init {
self = [super init];
self._children = NSMutableArray.new;
self._filteredChildren = self._children;
return self;
}
- (BOOL) isLeaf {
return self.count == 0;
}
- (NSArray*) children {
return self._children;
}
- (void) setChildren:(NSArray*)children {
self._children = children;
[self propagatePredicatesAndRefilterChildren];
}
- (NSArray*) filteredChildren {
return self._filteredChildren;
}
- (void) setFilteredChildren:(NSArray*)children {
assert(self._filteredChildren.count != children.count);
[self willChangeValueForKey:@"filteredChildren"];
self._filteredChildren = children;
self.count = children.count;
[self didChangeValueForKey:@"filteredChildren"];
}
- (NSPredicate*) predicate {
return self._predicate;
}
- (void) setPredicate:(NSPredicate*)predicate {
if (self._predicate != predicate) {
self._predicate = predicate;
if (self._children.count > 0) {
[self propagatePredicatesAndRefilterChildren];
}
}
}
- (void) propagatePredicatesAndRefilterChildren {
// Propagate the predicate down the child nodes in case either
// the predicate or the children array changed.
for (PredicateOutlineNode *child in self.children) {
child.predicate = self.predicate;
}
// Determine the matching leaf nodes.
NSArray *newChildren;
if (self.predicate != nil) {
newChildren = NSMutableArray.array;
for (PredicateOutlineNode *child in self._children) {
if (child.count > 0 || [self.predicate evaluateWithObject:child]) {
[(NSMutableArray*)newChildren addObject:child];
}
}
} else {
newChildren = self.children;
}
// Only actually update the children if the count varies.
if (newChildren.count != self.filteredChildren.count) {
self.filteredChildren = newChildren;
}
}
@end