search_bar.rs

  1use gpui::{
  2    elements::{Flex, Label, MouseEventHandler, ParentElement, Svg},
  3    platform::{CursorStyle, MouseButton},
  4    scene::MouseClick,
  5    Action, AnyElement, Element, EventContext, View, ViewContext,
  6};
  7use workspace::searchable::Direction;
  8
  9use crate::{
 10    elements::ButtonSide,
 11    mode::{SearchMode, Side},
 12    SearchOptions, SelectNextMatch, SelectPrevMatch,
 13};
 14
 15pub(super) fn render_close_button<V: View>(
 16    tooltip: &'static str,
 17    theme: &theme::Search,
 18    cx: &mut ViewContext<V>,
 19    on_click: impl Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
 20    dismiss_action: Option<Box<dyn Action>>,
 21) -> AnyElement<V> {
 22    let tooltip_style = theme::current(cx).tooltip.clone();
 23
 24    enum CloseButton {}
 25    MouseEventHandler::<CloseButton, _>::new(0, cx, |state, _| {
 26        let style = theme.dismiss_button.style_for(state);
 27        Svg::new("icons/x_mark_8.svg")
 28            .with_color(style.color)
 29            .constrained()
 30            .with_width(style.icon_width)
 31            .aligned()
 32            .constrained()
 33            .with_width(style.button_width)
 34            .contained()
 35            .with_style(style.container)
 36    })
 37    .on_click(MouseButton::Left, on_click)
 38    .with_cursor_style(CursorStyle::PointingHand)
 39    .with_tooltip::<CloseButton>(0, tooltip.to_string(), dismiss_action, tooltip_style, cx)
 40    .into_any()
 41}
 42
 43pub(super) fn render_nav_button<V: View>(
 44    icon: &'static str,
 45    direction: Direction,
 46    on_click: impl Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
 47    cx: &mut ViewContext<V>,
 48) -> AnyElement<V> {
 49    let action: Box<dyn Action>;
 50    let tooltip;
 51
 52    match direction {
 53        Direction::Prev => {
 54            action = Box::new(SelectPrevMatch);
 55            tooltip = "Select Previous Match";
 56        }
 57        Direction::Next => {
 58            action = Box::new(SelectNextMatch);
 59            tooltip = "Select Next Match";
 60        }
 61    };
 62    let tooltip_style = theme::current(cx).tooltip.clone();
 63
 64    enum NavButton {}
 65    MouseEventHandler::<NavButton, _>::new(direction as usize, cx, |state, cx| {
 66        let theme = theme::current(cx);
 67        let mut style = theme.search.nav_button.style_for(state).clone();
 68
 69        match direction {
 70            Direction::Prev => style.container.border.left = false,
 71            Direction::Next => style.container.border.right = false,
 72        };
 73        let label = Label::new(icon, style.label.clone())
 74            .contained()
 75            .with_style(style.container.clone());
 76        match direction {
 77            Direction::Prev => Flex::row()
 78                .with_child(
 79                    ButtonSide::left(
 80                        style
 81                            .clone()
 82                            .container
 83                            .background_color
 84                            .unwrap_or_else(gpui::color::Color::transparent_black),
 85                    )
 86                    .with_border(style.container.border.width, style.container.border.color)
 87                    .contained()
 88                    .constrained()
 89                    .with_max_width(theme.search.mode_filling_width),
 90                )
 91                .with_child(label)
 92                .constrained()
 93                .with_height(theme.workspace.toolbar.height),
 94            Direction::Next => Flex::row()
 95                .with_child(label)
 96                .with_child(
 97                    ButtonSide::right(
 98                        style
 99                            .clone()
100                            .container
101                            .background_color
102                            .unwrap_or_else(gpui::color::Color::transparent_black),
103                    )
104                    .with_border(style.container.border.width, style.container.border.color)
105                    .contained()
106                    .constrained()
107                    .with_max_width(theme.search.mode_filling_width),
108                )
109                .constrained()
110                .with_height(theme.workspace.toolbar.height),
111        }
112    })
113    .on_click(
114        MouseButton::Left,
115        on_click, /*move |_, this, cx| {
116                  if let Some(search) = this.active_project_search.as_ref() {
117                      search.update(cx, |search, cx| search.select_match(direction, cx));
118                      }*/
119    )
120    .with_cursor_style(CursorStyle::PointingHand)
121    .with_tooltip::<NavButton>(
122        direction as usize,
123        tooltip.to_string(),
124        Some(action),
125        tooltip_style,
126        cx,
127    )
128    .into_any()
129}
130
131pub(crate) fn render_search_mode_button<V: View>(
132    mode: SearchMode,
133    is_active: bool,
134    on_click: impl Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
135    cx: &mut ViewContext<V>,
136) -> AnyElement<V> {
137    let tooltip_style = theme::current(cx).tooltip.clone();
138    // let is_active = if let Some(search) = self.active_project_search.as_ref() {
139    //     let search = search.read(cx);
140    //     search.current_mode == mode
141    // } else {
142    //     false
143    // };
144
145    enum SearchModeButton {}
146    MouseEventHandler::<SearchModeButton, _>::new(mode.region_id(), cx, |state, cx| {
147        let theme = theme::current(cx);
148        let mut style = theme
149            .search
150            .mode_button
151            .in_state(is_active)
152            .style_for(state)
153            .clone();
154
155        let label = Label::new(mode.label(), style.text.clone())
156            .contained()
157            .with_style(style.container);
158
159        if let Some(button_side) = mode.button_side() {
160            style.container.border.left = mode.border_left();
161            style.container.border.right = mode.border_right();
162
163            if button_side == Side::Left {
164                Flex::row()
165                    .align_children_center()
166                    .with_child(
167                        ButtonSide::left(
168                            style
169                                .container
170                                .background_color
171                                .unwrap_or_else(gpui::color::Color::transparent_black),
172                        )
173                        .with_border(style.container.border.width, style.container.border.color)
174                        .contained()
175                        .constrained()
176                        .with_max_width(theme.search.mode_filling_width),
177                    )
178                    .with_child(label)
179                    .into_any()
180            } else {
181                Flex::row()
182                    .align_children_center()
183                    .with_child(label)
184                    .with_child(
185                        ButtonSide::right(
186                            style
187                                .container
188                                .background_color
189                                .unwrap_or_else(gpui::color::Color::transparent_black),
190                        )
191                        .with_border(style.container.border.width, style.container.border.color)
192                        .contained()
193                        .constrained()
194                        .with_max_width(theme.search.mode_filling_width),
195                    )
196                    .into_any()
197            }
198        } else {
199            label.into_any()
200        }
201    })
202    .on_click(MouseButton::Left, on_click)
203    .with_cursor_style(CursorStyle::PointingHand)
204    .with_tooltip::<SearchModeButton>(
205        mode.region_id(),
206        mode.tooltip_text().to_owned(),
207        Some(mode.activate_action()),
208        tooltip_style,
209        cx,
210    )
211    .into_any()
212}
213
214pub(crate) fn render_option_button_icon<V: View>(
215    is_active: bool,
216    icon: &'static str,
217    option: SearchOptions,
218    on_click: impl Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
219    cx: &mut ViewContext<V>,
220) -> AnyElement<V> {
221    let tooltip_style = theme::current(cx).tooltip.clone();
222    MouseEventHandler::<V, _>::new(option.bits as usize, cx, |state, cx| {
223        let theme = theme::current(cx);
224        let style = theme
225            .search
226            .option_button
227            .in_state(is_active)
228            .style_for(state);
229        Svg::new(icon)
230            .with_color(style.text.color.clone())
231            .contained()
232            .with_style(style.container)
233            .constrained()
234    })
235    .on_click(MouseButton::Left, on_click)
236    .with_cursor_style(CursorStyle::PointingHand)
237    .with_tooltip::<V>(
238        option.bits as usize,
239        format!("Toggle {}", option.label()),
240        Some(option.to_toggle_action()),
241        tooltip_style,
242        cx,
243    )
244    .into_any()
245}