Thread click handler through from workspace to language selector

Marshall Bowers created

Change summary

crates/ui2/src/components/icon_button.rs |  4 +-
crates/ui2/src/components/status_bar.rs  | 10 +++---
crates/ui2/src/components/workspace.rs   | 37 +++++++++++++++++++++++--
crates/ui2/src/elements/button.rs        | 13 ++++----
4 files changed, 46 insertions(+), 18 deletions(-)

Detailed changes

crates/ui2/src/components/icon_button.rs 🔗

@@ -4,10 +4,10 @@ use std::sync::Arc;
 use gpui3::{Interactive, MouseButton};
 
 use crate::prelude::*;
-use crate::{theme, Icon, IconColor, IconElement};
+use crate::{theme, ClickHandler, Icon, IconColor, IconElement};
 
 struct IconButtonHandlers<S: 'static + Send + Sync> {
-    click: Option<Arc<dyn Fn(&mut S, &mut ViewContext<S>) + 'static + Send + Sync>>,
+    click: Option<ClickHandler<S>>,
 }
 
 impl<S: 'static + Send + Sync> Default for IconButtonHandlers<S> {

crates/ui2/src/components/status_bar.rs 🔗

@@ -1,7 +1,7 @@
 use std::marker::PhantomData;
 
 use crate::prelude::*;
-use crate::{Button, Icon, IconButton, IconColor, ToolDivider};
+use crate::{Button, ClickHandler, Icon, IconButton, IconColor, ToolDivider};
 
 #[derive(Default, PartialEq)]
 pub enum Tool {
@@ -34,15 +34,17 @@ pub struct StatusBar<S: 'static + Send + Sync + Clone> {
     left_tools: Option<ToolGroup>,
     right_tools: Option<ToolGroup>,
     bottom_tools: Option<ToolGroup>,
+    on_select_language: ClickHandler<S>,
 }
 
 impl<S: 'static + Send + Sync + Clone> StatusBar<S> {
-    pub fn new() -> Self {
+    pub fn new(on_select_language: ClickHandler<S>) -> Self {
         Self {
             state_type: PhantomData,
             left_tools: None,
             right_tools: None,
             bottom_tools: None,
+            on_select_language,
         }
     }
 
@@ -119,9 +121,7 @@ impl<S: 'static + Send + Sync + Clone> StatusBar<S> {
                     .items_center()
                     .gap_1()
                     .child(Button::new("116:25"))
-                    .child(
-                        Button::new("Rust").on_click(|_, _| println!("Select Language clicked.")),
-                    ),
+                    .child(Button::new("Rust").on_click(self.on_select_language.clone())),
             )
             .child(ToolDivider::new())
             .child(

crates/ui2/src/components/workspace.rs 🔗

@@ -1,4 +1,5 @@
 use std::marker::PhantomData;
+use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::Arc;
 
 use chrono::DateTime;
@@ -7,9 +8,9 @@ use gpui3::{relative, rems, Size};
 use crate::prelude::*;
 use crate::{
     hello_world_rust_editor_with_status_example, random_players_with_call_status, theme, v_stack,
-    ChatMessage, ChatPanel, EditorPane, Label, Livestream, Pane, PaneGroup, Panel,
-    PanelAllowedSides, PanelSide, ProjectPanel, SplitDirection, StatusBar, Terminal, TitleBar,
-    Toast, ToastOrigin,
+    ChatMessage, ChatPanel, EditorPane, Label, LanguageSelector, Livestream, Pane, PaneGroup,
+    Panel, PanelAllowedSides, PanelSide, ProjectPanel, SplitDirection, StatusBar, Terminal,
+    TitleBar, Toast, ToastOrigin,
 };
 
 #[derive(Element)]
@@ -19,6 +20,7 @@ pub struct WorkspaceElement<S: 'static + Send + Sync + Clone> {
     right_panel_scroll_state: ScrollState,
     tab_bar_scroll_state: ScrollState,
     bottom_panel_scroll_state: ScrollState,
+    show_language_selector: Arc<AtomicBool>,
 }
 
 impl<S: 'static + Send + Sync + Clone> WorkspaceElement<S> {
@@ -29,12 +31,15 @@ impl<S: 'static + Send + Sync + Clone> WorkspaceElement<S> {
             right_panel_scroll_state: ScrollState::default(),
             tab_bar_scroll_state: ScrollState::default(),
             bottom_panel_scroll_state: ScrollState::default(),
+            show_language_selector: Arc::new(AtomicBool::new(false)),
         }
     }
 
     pub fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<State = S> {
         let theme = theme(cx).clone();
 
+        let show_language_selector = self.show_language_selector.clone();
+
         let temp_size = rems(36.).into();
 
         let root_group = PaneGroup::new_groups(
@@ -182,7 +187,31 @@ impl<S: 'static + Send + Sync + Clone> WorkspaceElement<S> {
                         .side(PanelSide::Right),
                     ),
             )
-            .child(StatusBar::new())
+            .child(StatusBar::new(Arc::new(move |_, cx| {
+                let is_showing_language_selector = show_language_selector.load(Ordering::SeqCst);
+
+                show_language_selector
+                    .compare_exchange(
+                        is_showing_language_selector,
+                        !is_showing_language_selector,
+                        Ordering::SeqCst,
+                        Ordering::SeqCst,
+                    )
+                    .unwrap();
+
+                cx.notify();
+            })))
+            .children(
+                Some(
+                    div()
+                        .absolute()
+                        .top_0()
+                        .left_0()
+                        .z_index(999)
+                        .child(LanguageSelector::new()),
+                )
+                .filter(|_| self.show_language_selector.load(Ordering::SeqCst)),
+            )
             .child(Toast::new(
                 ToastOrigin::Bottom,
                 |_, _| vec![Label::new("A toast").into_any()],

crates/ui2/src/elements/button.rs 🔗

@@ -20,8 +20,10 @@ pub enum ButtonVariant {
     Filled,
 }
 
+pub type ClickHandler<S> = Arc<dyn Fn(&mut S, &mut ViewContext<S>) + 'static + Send + Sync>;
+
 struct ButtonHandlers<S: 'static + Send + Sync> {
-    click: Option<Arc<dyn Fn(&mut S, &mut ViewContext<S>) + 'static + Send + Sync>>,
+    click: Option<ClickHandler<S>>,
 }
 
 impl<S: 'static + Send + Sync> Default for ButtonHandlers<S> {
@@ -94,11 +96,8 @@ impl<S: 'static + Send + Sync + Clone> Button<S> {
         self
     }
 
-    pub fn on_click(
-        mut self,
-        handler: impl Fn(&mut S, &mut ViewContext<S>) + 'static + Send + Sync,
-    ) -> Self {
-        self.handlers.click = Some(Arc::new(handler));
+    pub fn on_click(mut self, handler: ClickHandler<S>) -> Self {
+        self.handlers.click = Some(handler);
         self
     }
 
@@ -403,7 +402,7 @@ mod stories {
                 .child(
                     Button::new("Label")
                         .variant(ButtonVariant::Ghost)
-                        .on_click(|_view, _cx| println!("Button clicked.")),
+                        .on_click(Arc::new(|_view, _cx| println!("Button clicked."))),
                 )
         }
     }