1use std::io::Write;
2use std::time::Duration;
3
4use crate::task::{EventIndex, Task, TaskStore};
5use crate::{Renderer, TaskId};
6
7pub struct FrameWriter<'a> {
20 target: &'a mut dyn Write,
21 frame_lines: usize,
22}
23
24impl<'a> FrameWriter<'a> {
25 pub(crate) fn new(target: &'a mut dyn Write, frame_lines: usize) -> Self {
26 Self {
27 target,
28 frame_lines,
29 }
30 }
31
32 pub(crate) fn clear_frame(&mut self) -> Result<(), std::io::Error> {
33 let lines_drawn = self.frame_lines;
34 if lines_drawn > 0 {
35 write!(self, "\r\x1b[{}A\x1b[2K\x1b[J", lines_drawn).unwrap();
36 self.target.flush()?;
37 }
38 self.frame_lines = 0;
39 Ok(())
40 }
41
42 pub(crate) fn frame_lines(&self) -> usize {
43 self.frame_lines
44 }
45}
46
47impl<'a> Write for FrameWriter<'a> {
48 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
49 let newlines = buf.iter().filter(|&&b| b == b'\n').count();
50 self.frame_lines += newlines;
51 self.target.write(buf)
52 }
53
54 fn flush(&mut self) -> std::io::Result<()> {
55 self.target.flush()
56 }
57}
58
59#[derive(Clone, Copy)]
70pub struct TaskView<'a, R: Renderer> {
71 id: TaskId,
72 tasks: &'a TaskStore<R>,
73}
74
75impl<'a, R: Renderer> TaskView<'a, R> {
76 pub fn new(tasks: &'a TaskStore<R>, id: TaskId) -> Self {
78 Self { id, tasks }
79 }
80
81 pub fn id(&self) -> TaskId {
83 self.id
84 }
85
86 pub fn data(&self) -> &R::TaskData {
88 self.tasks.task(&self.id).data.as_ref().unwrap()
89 }
90
91 pub fn depth(&self) -> usize {
93 self.tasks.task(&self.id).depth
94 }
95
96 pub fn elapsed(&self) -> Duration {
98 self.tasks.task(&self.id).started_at.elapsed()
99 }
100
101 pub fn active(&self) -> bool {
103 !self.completed() && !self.cancelled()
104 }
105
106 pub fn completed(&self) -> bool {
108 self.tasks.task(&self.id).completed
109 }
110
111 pub fn cancelled(&self) -> bool {
113 self.tasks.task(&self.id).cancelled
114 }
115
116 pub fn parent<'b>(&'b self) -> Option<TaskView<'b, R>> {
118 self.tasks
119 .task(&self.id)
120 .parent
121 .map(|id| TaskView::new(self.tasks, id))
122 }
123
124 pub fn events<'b>(
126 &'b self,
127 ) -> impl DoubleEndedIterator<Item = EventView<'b, R>> + ExactSizeIterator {
128 (0..self.tasks.task(&self.id).events.len())
129 .map(move |id| EventView::new(self.tasks, self.id, id))
130 }
131
132 pub fn subtasks<'b>(
134 &'b self,
135 ) -> impl DoubleEndedIterator<Item = TaskView<'b, R>> + ExactSizeIterator {
136 self.tasks
137 .task(&self.id)
138 .subtasks
139 .iter()
140 .map(move |id| TaskView::new(self.tasks, *id))
141 }
142
143 pub fn index(&self) -> usize {
145 let parent = self.tasks.task(&self.id).parent.unwrap();
146 let parent = self.tasks.task(&parent);
147 parent.subtasks.get_index_of(&self.id).unwrap()
148 }
149
150 pub fn view(&self, id: TaskId) -> TaskView<'a, R> {
152 TaskView::new(self.tasks, id)
153 }
154}
155
156pub struct EventView<'a, R: Renderer> {
166 tasks: &'a TaskStore<R>,
167 task: TaskId,
168 id: EventIndex,
169}
170
171impl<'a, R: Renderer> EventView<'a, R> {
172 pub(crate) fn new(tasks: &'a TaskStore<R>, task: TaskId, id: usize) -> Self {
173 Self {
174 tasks,
175 task,
176 id: EventIndex(id),
177 }
178 }
179
180 pub fn is_root(&self) -> bool {
182 self.task == TaskId::ROOT
183 }
184
185 pub fn data(&self) -> &R::EventData {
187 let task = self.get_task();
188 task.events().get(self.id.0).unwrap()
189 }
190
191 pub fn depth(&self) -> usize {
193 self.get_task().depth
194 }
195
196 pub fn task<'b>(&'b self) -> TaskView<'b, R> {
198 TaskView::new(self.tasks, self.task)
199 }
200
201 fn get_task(&self) -> &Task<R> {
202 self.tasks.task(&self.task)
203 }
204}