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}