struct Directory: MenuItem {
/// Name of the directory. Used to display on the outline view.
let name: String
/// Children of the directory.
let children: [MenuItem]
/// Non empty children items only.
let nonEmptyChildren: [MenuItem]
/// Total count of the directory's children.
var childrenCount: Int {
var count = 0
for child in children {
if let directory = child as? Directory {
count += directory.isEmptyDirectory ? 0 : 1
} else {
count += 1
}
}
return count
}
/// Determines if the directory is empty.
var isEmptyDirectory: Bool {
var isEmpty = true
for child in children {
if let directory = child as? Directory {
isEmpty = isEmpty && directory.isEmptyDirectory
} else {
return false
}
}
return isEmpty
}
init(name: String, children: [MenuItem]) {
self.name = name
self.children = children
nonEmptyChildren = children.filter { !(($0 as? Directory)?.isEmptyDirectory ?? false) }
}
/// Filters the children items with the given parameters.
///
/// - Parameter filter: String to filter children by.
/// - Returns: Updated directory object with children filtered.
func filter(_ filter: String) -> Directory {
guard !filter.isEmpty else {
return self
}
let filteredChildren = children.compactMap { matchedChild(filter: filter, child: $0) }
return Directory(name: name, children: filteredChildren)
}
/// Returns the matched child of the filter provided.
///
/// - Parameters:
/// - filter: Filter to check for.
/// - child: Child used to check its name against.
/// - Returns: Optional menu item.
func matchedChild(filter: String, child: MenuItem) -> MenuItem? {
if let directory = child as? Directory {
return directory.filter(filter)
} else if let fileItem = child as? FileItem, child.name.lowercased().contains(filter.lowercased()) {
return fileItem
}
return nil
}
}