use gpui::Context;
use std::time::Duration;
pub struct CursorBlink {
interval: Duration,
generation: usize,
visible: bool,
active: bool,
paused: bool,
}
impl CursorBlink {
pub fn new(interval: Duration, _cx: &mut Context<Self>) -> Self {
Self {
interval,
generation: 0,
visible: true,
active: false,
paused: false,
}
}
pub fn visible(&self) -> bool {
self.visible
}
pub fn is_active(&self) -> bool {
self.active
}
pub fn enable(&mut self, cx: &mut Context<Self>) {
if self.active {
return;
}
self.active = true;
self.visible = false;
self.paused = false;
self.tick(cx);
}
pub fn disable(&mut self, cx: &mut Context<Self>) {
self.active = false;
self.visible = false;
self.paused = false;
cx.notify();
}
pub fn pause_blinking(&mut self, cx: &mut Context<Self>) {
if !self.visible {
self.visible = true;
cx.notify();
}
self.paused = true;
self.generation = self.generation.wrapping_add(1);
let generation = self.generation;
let interval = self.interval;
cx.spawn(async move |this, cx| {
let timer = cx.background_executor().timer(interval);
timer.await;
this.update(cx, |this, cx| {
if this.generation == generation {
this.paused = false;
this.tick(cx);
}
})
})
.detach();
}
fn tick(&mut self, cx: &mut Context<Self>) {
if !self.active || self.paused {
return;
}
self.visible = !self.visible;
cx.notify();
self.generation = self.generation.wrapping_add(1);
let generation = self.generation;
let interval = self.interval;
cx.spawn(async move |this, cx| {
let timer = cx.background_executor().timer(interval);
timer.await;
if let Some(this) = this.upgrade() {
this.update(cx, |this, cx| {
if this.generation == generation {
this.tick(cx);
}
});
}
})
.detach();
}
}