mode_indicator.rs

 1use gpui::{div, AnyElement, Div, Element, Entity, IntoElement, Render, Subscription, ViewContext};
 2use settings::{Settings, SettingsStore};
 3use workspace::{item::ItemHandle, ui::Label, StatusItemView};
 4
 5use crate::{state::Mode, Vim, VimEvent, VimModeSetting};
 6
 7pub struct ModeIndicator {
 8    pub mode: Option<Mode>,
 9    // _subscription: Subscription,
10}
11
12impl ModeIndicator {
13    pub fn new(cx: &mut ViewContext<Self>) -> Self {
14        let handle = cx.view().downgrade();
15
16        // let _subscription = cx.subscribe_global::<VimEvent, _>(move |&event, cx| {
17        //     if let Some(mode_indicator) = handle.upgrade(cx) {
18        //         match event {
19        //             VimEvent::ModeChanged { mode } => {
20        //                 mode_indicator.window().update(cx, |cx| {
21        //                     mode_indicator.update(cx, move |mode_indicator, cx| {
22        //                         mode_indicator.set_mode(mode, cx);
23        //                     })
24        //                 });
25        //             }
26        //         }
27        //     }
28        // });
29
30        cx.observe_global::<SettingsStore>(move |mode_indicator, cx| {
31            if VimModeSetting::get_global(cx).0 {
32                mode_indicator.mode = cx
33                    .has_global::<Vim>()
34                    .then(|| cx.global::<Vim>().state().mode);
35            } else {
36                mode_indicator.mode.take();
37            }
38        })
39        .detach();
40
41        // Vim doesn't exist in some tests
42        let mode = cx
43            .has_global::<Vim>()
44            .then(|| {
45                let vim = cx.global::<Vim>();
46                vim.enabled.then(|| vim.state().mode)
47            })
48            .flatten();
49
50        Self {
51            mode,
52            //    _subscription,
53        }
54    }
55
56    pub fn set_mode(&mut self, mode: Mode, cx: &mut ViewContext<Self>) {
57        if self.mode != Some(mode) {
58            self.mode = Some(mode);
59            cx.notify();
60        }
61    }
62}
63
64impl Render for ModeIndicator {
65    type Element = AnyElement;
66
67    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement {
68        let Some(mode) = self.mode.as_ref() else {
69            return div().into_any();
70        };
71
72        let text = match mode {
73            Mode::Normal => "-- NORMAL --",
74            Mode::Insert => "-- INSERT --",
75            Mode::Visual => "-- VISUAL --",
76            Mode::VisualLine => "-- VISUAL LINE --",
77            Mode::VisualBlock => "-- VISUAL BLOCK --",
78        };
79        Label::new(text).into_any_element()
80    }
81}
82
83impl StatusItemView for ModeIndicator {
84    fn set_active_pane_item(
85        &mut self,
86        _active_pane_item: Option<&dyn ItemHandle>,
87        _cx: &mut ViewContext<Self>,
88    ) {
89        // nothing to do.
90    }
91}