/// 약속 (E5a): 가 본 폴더 내역 하나 (창마다). 입력 = 다른 폴더로 감 [visit] · 뒤로/앞으로 [take] → [arrive] → [finish], /// 출력 = 돌아갈 곳 (없으면 null) · [canBack] · [canForward]. 오류 없음. /// - [visit]: 다른 곳으로 가면 떠난 곳을 뒤로에 넣고 앞으로를 비운다. 같은 곳 · 빈 경로 · 뒤로/앞으로로 움직이는 중에는 넣지 않는다. /// - 뒤로는 [limit] 개까지 (넘으면 가장 오래된 것부터 버림). /// - 뒤로/앞으로가 끝나기 전에 또 부르면 null (빨리 두 번 눌러 두 칸이 빠지지 않게). /// - 같은 경로인지는 [same] 으로 (탐색기는 Windows 대소문자 무시 · WebDAV 주소를 아는 samePath). class NavHistory { NavHistory({this.limit = 50, required this.same}); final int limit; final bool Function(String a, String b) same; final back = []; final forward = []; /// 뒤로/앞으로로 움직이는 중 ([take] 부터 [arrive] 까지) bool traveling = false; bool get canBack => back.isNotEmpty; bool get canForward => forward.isNotEmpty; /// [from] 에서 [to] 로 감 (보통의 이동) void visit(String from, String to) { if (traveling || from.isEmpty || to.isEmpty || same(from, to)) return; back.add(from); if (back.length > limit) back.removeAt(0); forward.clear(); } /// 뒤로 ([forward] false) · 앞으로 갈 곳을 꺼낸다. 없거나 움직이는 중이면 null. /// 꺼낸 뒤 갈 수 있으면 [arrive] → (그곳으로 이동) → [finish], 갈 수 없으면 (지워짐 등) [finish] 만 - 그 항목은 버린다 String? take({required bool forward}) { final from = forward ? this.forward : back; if (traveling || from.isEmpty) return null; traveling = true; return from.removeLast(); } /// [take] 로 꺼낸 곳으로 감: 떠난 [current] 는 반대쪽 내역에 (이동하는 동안은 [visit] 이 넣지 않음) void arrive(String current, {required bool forward}) => (forward ? back : this.forward).add(current); /// 뒤로/앞으로 끝 (닿았든 못 갔든) void finish() => traveling = false; }