1use editor::Editor;
 2use gpui::{
 3    Context, Entity, IntoElement, ParentElement, Render, Styled, Subscription, WeakEntity, Window,
 4    div,
 5};
 6use language::LanguageName;
 7use settings::Settings as _;
 8use ui::{Button, ButtonCommon, Clickable, FluentBuilder, LabelSize, Tooltip};
 9use workspace::{StatusBarSettings, StatusItemView, Workspace, item::ItemHandle};
10
11use crate::{LanguageSelector, Toggle};
12
13pub struct ActiveBufferLanguage {
14    active_language: Option<Option<LanguageName>>,
15    workspace: WeakEntity<Workspace>,
16    _observe_active_editor: Option<Subscription>,
17}
18
19impl ActiveBufferLanguage {
20    pub fn new(workspace: &Workspace) -> Self {
21        Self {
22            active_language: None,
23            workspace: workspace.weak_handle(),
24            _observe_active_editor: None,
25        }
26    }
27
28    fn update_language(&mut self, editor: Entity<Editor>, _: &mut Window, cx: &mut Context<Self>) {
29        self.active_language = Some(None);
30
31        let editor = editor.read(cx);
32        if let Some((_, buffer, _)) = editor.active_excerpt(cx)
33            && let Some(language) = buffer.read(cx).language()
34        {
35            self.active_language = Some(Some(language.name()));
36        }
37
38        cx.notify();
39    }
40}
41
42impl Render for ActiveBufferLanguage {
43    fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
44        if !StatusBarSettings::get_global(cx).active_language_button {
45            return div().hidden();
46        }
47
48        div().when_some(self.active_language.as_ref(), |el, active_language| {
49            let active_language_text = if let Some(active_language_text) = active_language {
50                active_language_text.to_string()
51            } else {
52                "Unknown".to_string()
53            };
54
55            el.child(
56                Button::new("change-language", active_language_text)
57                    .label_size(LabelSize::Small)
58                    .on_click(cx.listener(|this, _, window, cx| {
59                        if let Some(workspace) = this.workspace.upgrade() {
60                            workspace.update(cx, |workspace, cx| {
61                                LanguageSelector::toggle(workspace, window, cx)
62                            });
63                        }
64                    }))
65                    .tooltip(|_window, cx| Tooltip::for_action("Select Language", &Toggle, cx)),
66            )
67        })
68    }
69}
70
71impl StatusItemView for ActiveBufferLanguage {
72    fn set_active_pane_item(
73        &mut self,
74        active_pane_item: Option<&dyn ItemHandle>,
75        window: &mut Window,
76        cx: &mut Context<Self>,
77    ) {
78        if let Some(editor) = active_pane_item.and_then(|item| item.downcast::<Editor>()) {
79            self._observe_active_editor =
80                Some(cx.observe_in(&editor, window, Self::update_language));
81            self.update_language(editor, window, cx);
82        } else {
83            self.active_language = None;
84            self._observe_active_editor = None;
85        }
86
87        cx.notify();
88    }
89}