use gpui::{ elements::{Empty, Label}, AnyElement, Element, Entity, Subscription, View, ViewContext, }; use settings::SettingsStore; use workspace::{item::ItemHandle, StatusItemView}; use crate::{state::Mode, Vim, VimEvent, VimModeSetting}; pub struct ModeIndicator { pub mode: Option, _subscription: Subscription, } impl ModeIndicator { pub fn new(cx: &mut ViewContext) -> Self { let handle = cx.handle().downgrade(); let _subscription = cx.subscribe_global::(move |&event, cx| { if let Some(mode_indicator) = handle.upgrade(cx) { match event { VimEvent::ModeChanged { mode } => { mode_indicator.window().update(cx, |cx| { mode_indicator.update(cx, move |mode_indicator, cx| { mode_indicator.set_mode(mode, cx); }) }); } } } }); cx.observe_global::(move |mode_indicator, cx| { if settings::get::(cx).0 { mode_indicator.mode = cx .has_global::() .then(|| cx.global::().state().mode); } else { mode_indicator.mode.take(); } }) .detach(); // Vim doesn't exist in some tests let mode = cx .has_global::() .then(|| { let vim = cx.global::(); vim.enabled.then(|| vim.state().mode) }) .flatten(); Self { mode, _subscription, } } pub fn set_mode(&mut self, mode: Mode, cx: &mut ViewContext) { if self.mode != Some(mode) { self.mode = Some(mode); cx.notify(); } } } impl Entity for ModeIndicator { type Event = (); } impl View for ModeIndicator { fn ui_name() -> &'static str { "ModeIndicatorView" } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { let Some(mode) = self.mode.as_ref() else { return Empty::new().into_any(); }; let theme = &theme::current(cx).workspace.status_bar; let text = match mode { Mode::Normal => "-- NORMAL --", Mode::Insert => "-- INSERT --", Mode::Visual => "-- VISUAL --", Mode::VisualLine => "-- VISUAL LINE --", Mode::VisualBlock => "-- VISUAL BLOCK --", }; Label::new(text, theme.vim_mode_indicator.text.clone()) .contained() .with_style(theme.vim_mode_indicator.container) .into_any() } } impl StatusItemView for ModeIndicator { fn set_active_pane_item( &mut self, _active_pane_item: Option<&dyn ItemHandle>, _cx: &mut ViewContext, ) { // nothing to do. } }