Optimize and simplify the BlinkCursor. (#133)
This commit is contained in:
parent
bb6d8d8f60
commit
b301c5b8fe
3 changed files with 19 additions and 38 deletions
|
|
@ -2,69 +2,57 @@ 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 struct BlinkCursor {
|
||||
interval: Duration,
|
||||
blink_epoch: usize,
|
||||
pub(crate) struct BlinkCursor {
|
||||
visible: bool,
|
||||
paused: bool,
|
||||
started: bool,
|
||||
epoch: usize,
|
||||
}
|
||||
|
||||
impl BlinkCursor {
|
||||
pub fn new(_cx: &mut ModelContext<Self>) -> Self {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
interval: Duration::from_millis(500),
|
||||
visible: false,
|
||||
paused: false,
|
||||
started: false,
|
||||
blink_epoch: 0,
|
||||
epoch: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Start the blinking
|
||||
pub fn start(&mut self, cx: &mut ModelContext<Self>) {
|
||||
if self.started {
|
||||
return;
|
||||
}
|
||||
|
||||
self.started = true;
|
||||
self.blink(self.blink_epoch, cx);
|
||||
self.blink(self.epoch, cx);
|
||||
}
|
||||
|
||||
pub fn stop(&mut self, cx: &mut ModelContext<Self>) {
|
||||
self.started = false;
|
||||
self.epoch = 0;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn next_epoch(&mut self) -> usize {
|
||||
self.blink_epoch += 1;
|
||||
self.blink_epoch
|
||||
self.epoch += 1;
|
||||
self.epoch
|
||||
}
|
||||
|
||||
fn blink(&mut self, epoch: usize, cx: &mut ModelContext<Self>) {
|
||||
if self.paused || !self.started {
|
||||
return;
|
||||
}
|
||||
|
||||
if epoch != self.blink_epoch {
|
||||
if self.paused || epoch != self.epoch {
|
||||
return;
|
||||
}
|
||||
|
||||
self.visible = !self.visible;
|
||||
cx.notify();
|
||||
|
||||
let epoch = self.next_epoch();
|
||||
|
||||
// Schedule the next blink
|
||||
let interval = self.interval;
|
||||
let epoch = self.next_epoch();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
Timer::after(interval).await;
|
||||
Timer::after(INTERVAL).await;
|
||||
if let Some(this) = this.upgrade() {
|
||||
this.update(&mut cx, |this, cx| this.blink(epoch, cx)).ok();
|
||||
}
|
||||
|
|
@ -74,28 +62,21 @@ impl BlinkCursor {
|
|||
|
||||
pub fn visible(&self) -> bool {
|
||||
// Keep showing the cursor if paused
|
||||
if self.paused {
|
||||
return true;
|
||||
}
|
||||
self.visible
|
||||
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;
|
||||
self.next_epoch();
|
||||
cx.notify();
|
||||
|
||||
let epoch = self.next_epoch();
|
||||
// delay 500ms to start the blinking
|
||||
let epoch = self.next_epoch();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
Timer::after(Duration::from_secs_f64(0.5)).await;
|
||||
Timer::after(PAUSE_DELAY).await;
|
||||
|
||||
if let Some(this) = this.upgrade() {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
if epoch != this.blink_epoch {
|
||||
return;
|
||||
}
|
||||
this.paused = false;
|
||||
this.blink(epoch, cx);
|
||||
})
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ impl EventEmitter<InputEvent> for TextInput {}
|
|||
impl TextInput {
|
||||
pub fn new(cx: &mut ViewContext<Self>) -> Self {
|
||||
let focus_handle = cx.focus_handle();
|
||||
let blink_cursor = cx.new_model(|cx| BlinkCursor::new(cx));
|
||||
let blink_cursor = cx.new_model(|_| BlinkCursor::new());
|
||||
let history = History::new();
|
||||
let input = Self {
|
||||
focus_handle: focus_handle.clone(),
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ pub struct OtpInput {
|
|||
impl OtpInput {
|
||||
pub fn new(length: usize, cx: &mut ViewContext<Self>) -> Self {
|
||||
let focus_handle = cx.focus_handle();
|
||||
let blink_cursor = cx.new_model(|cx| BlinkCursor::new(cx));
|
||||
let blink_cursor = cx.new_model(|_| BlinkCursor::new());
|
||||
let input = Self {
|
||||
focus_handle: focus_handle.clone(),
|
||||
length,
|
||||
|
|
|
|||
Loading…
Reference in a new issue