blink_manager.rs

  1use crate::EditorSettings;
  2use gpui::Context;
  3use settings::Settings;
  4use settings::SettingsStore;
  5use smol::Timer;
  6use std::time::Duration;
  7
  8pub struct BlinkManager {
  9    blink_interval: Duration,
 10
 11    blink_epoch: usize,
 12    blinking_paused: bool,
 13    visible: bool,
 14    enabled: bool,
 15}
 16
 17impl BlinkManager {
 18    pub fn new(blink_interval: Duration, cx: &mut Context<Self>) -> Self {
 19        // Make sure we blink the cursors if the setting is re-enabled
 20        cx.observe_global::<SettingsStore>(move |this, cx| {
 21            this.blink_cursors(this.blink_epoch, cx)
 22        })
 23        .detach();
 24
 25        Self {
 26            blink_interval,
 27
 28            blink_epoch: 0,
 29            blinking_paused: false,
 30            visible: true,
 31            enabled: false,
 32        }
 33    }
 34
 35    fn next_blink_epoch(&mut self) -> usize {
 36        self.blink_epoch += 1;
 37        self.blink_epoch
 38    }
 39
 40    pub fn pause_blinking(&mut self, cx: &mut Context<Self>) {
 41        self.show_cursor(cx);
 42
 43        let epoch = self.next_blink_epoch();
 44        let interval = self.blink_interval;
 45        cx.spawn(|this, mut cx| async move {
 46            Timer::after(interval).await;
 47            this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
 48        })
 49        .detach();
 50    }
 51
 52    fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut Context<Self>) {
 53        if epoch == self.blink_epoch {
 54            self.blinking_paused = false;
 55            self.blink_cursors(epoch, cx);
 56        }
 57    }
 58
 59    fn blink_cursors(&mut self, epoch: usize, cx: &mut Context<Self>) {
 60        if EditorSettings::get_global(cx).cursor_blink {
 61            if epoch == self.blink_epoch && self.enabled && !self.blinking_paused {
 62                self.visible = !self.visible;
 63                cx.notify();
 64
 65                let epoch = self.next_blink_epoch();
 66                let interval = self.blink_interval;
 67                cx.spawn(|this, mut cx| async move {
 68                    Timer::after(interval).await;
 69                    if let Some(this) = this.upgrade() {
 70                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx))
 71                            .ok();
 72                    }
 73                })
 74                .detach();
 75            }
 76        } else {
 77            self.show_cursor(cx);
 78        }
 79    }
 80
 81    pub fn show_cursor(&mut self, cx: &mut Context<'_, BlinkManager>) {
 82        if !self.visible {
 83            self.visible = true;
 84            cx.notify();
 85        }
 86    }
 87
 88    pub fn enable(&mut self, cx: &mut Context<Self>) {
 89        if self.enabled {
 90            return;
 91        }
 92
 93        self.enabled = true;
 94        // Set cursors as invisible and start blinking: this causes cursors
 95        // to be visible during the next render.
 96        self.visible = false;
 97        self.blink_cursors(self.blink_epoch, cx);
 98    }
 99
100    pub fn disable(&mut self, _cx: &mut Context<Self>) {
101        self.visible = false;
102        self.enabled = false;
103    }
104
105    pub fn visible(&self) -> bool {
106        self.visible
107    }
108}