move gpui-components to ui crate
This commit is contained in:
88
crates/ui/src/input/blink_cursor.rs
Normal file
88
crates/ui/src/input/blink_cursor.rs
Normal file
@@ -0,0 +1,88 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use gpui::{ModelContext, Timer};
|
||||
|
||||
static INTERVAL: Duration = Duration::from_millis(500);
|
||||
static PAUSE_DELAY: Duration = Duration::from_millis(300);
|
||||
|
||||
/// To manage the Input cursor blinking.
|
||||
///
|
||||
/// It will start blinking with a interval of 500ms.
|
||||
/// Every loop will notify the view to update the `visible`, and Input will observe this update to touch repaint.
|
||||
///
|
||||
/// The input painter will check if this in visible state, then it will draw the cursor.
|
||||
pub(crate) struct BlinkCursor {
|
||||
visible: bool,
|
||||
paused: bool,
|
||||
epoch: usize,
|
||||
}
|
||||
|
||||
impl BlinkCursor {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
visible: false,
|
||||
paused: false,
|
||||
epoch: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Start the blinking
|
||||
pub fn start(&mut self, cx: &mut ModelContext<Self>) {
|
||||
self.blink(self.epoch, cx);
|
||||
}
|
||||
|
||||
pub fn stop(&mut self, cx: &mut ModelContext<Self>) {
|
||||
self.epoch = 0;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn next_epoch(&mut self) -> usize {
|
||||
self.epoch += 1;
|
||||
self.epoch
|
||||
}
|
||||
|
||||
fn blink(&mut self, epoch: usize, cx: &mut ModelContext<Self>) {
|
||||
if self.paused || epoch != self.epoch {
|
||||
return;
|
||||
}
|
||||
|
||||
self.visible = !self.visible;
|
||||
cx.notify();
|
||||
|
||||
// Schedule the next blink
|
||||
let epoch = self.next_epoch();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
Timer::after(INTERVAL).await;
|
||||
if let Some(this) = this.upgrade() {
|
||||
this.update(&mut cx, |this, cx| this.blink(epoch, cx)).ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
pub fn visible(&self) -> bool {
|
||||
// Keep showing the cursor if paused
|
||||
self.paused || self.visible
|
||||
}
|
||||
|
||||
/// Pause the blinking, and delay 500ms to resume the blinking.
|
||||
pub fn pause(&mut self, cx: &mut ModelContext<Self>) {
|
||||
self.paused = true;
|
||||
cx.notify();
|
||||
|
||||
// delay 500ms to start the blinking
|
||||
let epoch = self.next_epoch();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
Timer::after(PAUSE_DELAY).await;
|
||||
|
||||
if let Some(this) = this.upgrade() {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.paused = false;
|
||||
this.blink(epoch, cx);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user