tab_stop.rs

  1use gpui::{
  2    App, Application, Bounds, Context, Div, ElementId, FocusHandle, KeyBinding, SharedString,
  3    Stateful, Window, WindowBounds, WindowOptions, actions, div, prelude::*, px, size,
  4};
  5
  6actions!(example, [Tab, TabPrev]);
  7
  8struct Example {
  9    items: Vec<FocusHandle>,
 10    message: SharedString,
 11}
 12
 13impl Example {
 14    fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
 15        let items = vec![
 16            cx.focus_handle().tab_index(1).tab_stop(true),
 17            cx.focus_handle().tab_index(2).tab_stop(true),
 18            cx.focus_handle().tab_index(3).tab_stop(true),
 19            cx.focus_handle(),
 20            cx.focus_handle().tab_index(2).tab_stop(true),
 21        ];
 22
 23        window.focus(items.first().unwrap());
 24        Self {
 25            items,
 26            message: SharedString::from("Press `Tab`, `Shift-Tab` to switch focus."),
 27        }
 28    }
 29
 30    fn on_tab(&mut self, _: &Tab, window: &mut Window, _: &mut Context<Self>) {
 31        window.focus_next();
 32        self.message = SharedString::from("You have pressed `Tab`.");
 33    }
 34
 35    fn on_tab_prev(&mut self, _: &TabPrev, window: &mut Window, _: &mut Context<Self>) {
 36        window.focus_prev();
 37        self.message = SharedString::from("You have pressed `Shift-Tab`.");
 38    }
 39}
 40
 41impl Render for Example {
 42    fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
 43        fn button(id: impl Into<ElementId>) -> Stateful<Div> {
 44            div()
 45                .id(id)
 46                .h_10()
 47                .flex_1()
 48                .flex()
 49                .justify_center()
 50                .items_center()
 51                .border_1()
 52                .border_color(gpui::black())
 53                .bg(gpui::black())
 54                .text_color(gpui::white())
 55                .focus(|this| this.border_color(gpui::blue()))
 56                .shadow_sm()
 57        }
 58
 59        div()
 60            .id("app")
 61            .on_action(cx.listener(Self::on_tab))
 62            .on_action(cx.listener(Self::on_tab_prev))
 63            .size_full()
 64            .flex()
 65            .flex_col()
 66            .p_4()
 67            .gap_3()
 68            .bg(gpui::white())
 69            .text_color(gpui::black())
 70            .child(self.message.clone())
 71            .children(
 72                self.items
 73                    .clone()
 74                    .into_iter()
 75                    .enumerate()
 76                    .map(|(ix, item_handle)| {
 77                        div()
 78                            .id(("item", ix))
 79                            .track_focus(&item_handle)
 80                            .h_10()
 81                            .w_full()
 82                            .flex()
 83                            .justify_center()
 84                            .items_center()
 85                            .border_1()
 86                            .border_color(gpui::black())
 87                            .when(
 88                                item_handle.tab_stop && item_handle.is_focused(window),
 89                                |this| this.border_color(gpui::blue()),
 90                            )
 91                            .map(|this| match item_handle.tab_stop {
 92                                true => this
 93                                    .hover(|this| this.bg(gpui::black().opacity(0.1)))
 94                                    .child(format!("tab_index: {}", item_handle.tab_index)),
 95                                false => this.opacity(0.4).child("tab_stop: false"),
 96                            })
 97                    }),
 98            )
 99            .child(
100                div()
101                    .flex()
102                    .flex_row()
103                    .gap_3()
104                    .items_center()
105                    .child(button("el1").tab_index(4).child("Button 1"))
106                    .child(button("el2").tab_index(5).child("Button 2")),
107            )
108    }
109}
110
111fn main() {
112    Application::new().run(|cx: &mut App| {
113        cx.bind_keys([
114            KeyBinding::new("tab", Tab, None),
115            KeyBinding::new("shift-tab", TabPrev, None),
116        ]);
117
118        let bounds = Bounds::centered(None, size(px(800.), px(600.0)), cx);
119        cx.open_window(
120            WindowOptions {
121                window_bounds: Some(WindowBounds::Windowed(bounds)),
122                ..Default::default()
123            },
124            |window, cx| cx.new(|cx| Example::new(window, cx)),
125        )
126        .unwrap();
127
128        cx.activate(true);
129    });
130}