Skip to repository content793 lines · 38.6 KB · rust
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T06:53:14.905Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
quick_action_bar.rs
1mod preview;
2mod repl_menu;
3
4use agent_settings::AgentSettings;
5use editor::actions::{
6 AddSelectionAbove, AddSelectionBelow, CodeActionSource, DuplicateLineDown, GoToDiagnostic,
7 GoToHunk, GoToPreviousDiagnostic, GoToPreviousHunk, MoveLineDown, MoveLineUp, SelectAll,
8 SelectLargerSyntaxNode, SelectNext, SelectSmallerSyntaxNode, ToggleCodeActions,
9 ToggleDiagnostics, ToggleGoToLine, ToggleInlineDiagnostics,
10};
11use editor::code_context_menus::{CodeContextMenu, ContextMenuOrigin};
12use editor::{Editor, EditorSettings};
13use gpui::{
14 Action, Anchor, AnchoredPositionMode, ClickEvent, Context, ElementId, Entity, EventEmitter,
15 FocusHandle, Focusable, InteractiveElement, ParentElement, Render, Styled, Subscription,
16 WeakEntity, Window, anchored, deferred, point,
17};
18use project::{DisableAiSettings, project_settings::DiagnosticSeverity};
19use search::{BufferSearchBar, buffer_search};
20use settings::{Settings, SettingsStore};
21use ui::{
22 ButtonStyle, ContextMenu, ContextMenuEntry, DocumentationSide, IconButton, IconName, IconSize,
23 PopoverMenu, PopoverMenuHandle, Tooltip, prelude::*,
24};
25use vim_mode_setting::{HelixModeSetting, VimModeSetting};
26use workspace::item::ItemBufferKind;
27use workspace::{
28 ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, Workspace, item::ItemHandle,
29};
30use zed_actions::{agent::AddSelectionToThread, assistant::InlineAssist, outline::ToggleOutline};
31
32const MAX_CODE_ACTION_MENU_LINES: u32 = 16;
33
34pub struct QuickActionBar {
35 _inlay_hints_enabled_subscription: Option<Subscription>,
36 _ai_settings_subscription: Subscription,
37 active_item: Option<Box<dyn ItemHandle>>,
38 buffer_search_bar: Entity<BufferSearchBar>,
39 show: bool,
40 toggle_selections_handle: PopoverMenuHandle<ContextMenu>,
41 toggle_settings_handle: PopoverMenuHandle<ContextMenu>,
42 workspace: WeakEntity<Workspace>,
43}
44
45impl QuickActionBar {
46 pub fn new(
47 buffer_search_bar: Entity<BufferSearchBar>,
48 workspace: &Workspace,
49 cx: &mut Context<Self>,
50 ) -> Self {
51 let mut was_agent_enabled = AgentSettings::get_global(cx).enabled(cx);
52 let mut was_agent_button = AgentSettings::get_global(cx).button;
53
54 let ai_settings_subscription = cx.observe_global::<SettingsStore>(move |_, cx| {
55 let agent_settings = AgentSettings::get_global(cx);
56 let is_agent_enabled = agent_settings.enabled(cx);
57
58 if was_agent_enabled != is_agent_enabled || was_agent_button != agent_settings.button {
59 was_agent_enabled = is_agent_enabled;
60 was_agent_button = agent_settings.button;
61 cx.notify();
62 }
63 });
64
65 let mut this = Self {
66 _inlay_hints_enabled_subscription: None,
67 _ai_settings_subscription: ai_settings_subscription,
68 active_item: None,
69 buffer_search_bar,
70 show: true,
71 toggle_selections_handle: Default::default(),
72 toggle_settings_handle: Default::default(),
73 workspace: workspace.weak_handle(),
74 };
75 this.apply_settings(cx);
76 cx.observe_global::<SettingsStore>(|this, cx| this.apply_settings(cx))
77 .detach();
78 this
79 }
80
81 fn active_editor(&self) -> Option<Entity<Editor>> {
82 self.active_item
83 .as_ref()
84 .and_then(|item| item.downcast::<Editor>())
85 }
86
87 fn apply_settings(&mut self, cx: &mut Context<Self>) {
88 let new_show = EditorSettings::get_global(cx).toolbar.quick_actions;
89 if new_show != self.show {
90 self.show = new_show;
91 cx.emit(ToolbarItemEvent::ChangeLocation(
92 self.get_toolbar_item_location(),
93 ));
94 }
95 }
96
97 fn get_toolbar_item_location(&self) -> ToolbarItemLocation {
98 if self.show && self.active_editor().is_some() {
99 ToolbarItemLocation::PrimaryRight
100 } else {
101 ToolbarItemLocation::Hidden
102 }
103 }
104}
105
106impl Render for QuickActionBar {
107 fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
108 let Some(editor) = self.active_editor() else {
109 return div().id("empty quick action bar");
110 };
111
112 let supports_inlay_hints = editor.update(cx, |editor, cx| editor.supports_inlay_hints(cx));
113 let supports_semantic_tokens =
114 editor.update(cx, |editor, cx| editor.supports_semantic_tokens(cx));
115 let supports_code_lens = editor.update(cx, |editor, cx| editor.supports_code_lens(cx));
116 let editor_value = editor.read(cx);
117 let selection_menu_enabled = editor_value.selection_menu_enabled(cx);
118 let inlay_hints_enabled = editor_value.inlay_hints_enabled();
119 let inline_values_enabled = editor_value.inline_values_enabled();
120 let semantic_highlights_enabled = editor_value.semantic_highlights_enabled();
121 let code_lens_enabled = editor_value.code_lens_enabled();
122 let is_full = editor_value.mode().is_full();
123 let diagnostics_enabled = editor_value.diagnostics_enabled()
124 && editor_value.diagnostics_max_severity != DiagnosticSeverity::Off;
125 let supports_inline_diagnostics = editor_value.inline_diagnostics_enabled();
126 let inline_diagnostics_enabled = editor_value.show_inline_diagnostics();
127 let git_blame_inline_enabled = editor_value.git_blame_inline_enabled();
128 let show_git_blame_gutter = editor_value.show_git_blame_gutter();
129 let auto_signature_help_enabled = editor_value.auto_signature_help_enabled(cx);
130 let show_line_numbers = editor_value.line_numbers_enabled(cx);
131 let has_edit_prediction_provider = editor_value.edit_prediction_provider().is_some();
132 let show_edit_predictions = editor_value.edit_predictions_enabled();
133 let edit_predictions_enabled_at_cursor =
134 editor_value.edit_predictions_enabled_at_cursor(cx);
135 let supports_minimap = editor_value.supports_minimap(cx);
136 let minimap_enabled = supports_minimap && editor_value.minimap().is_some();
137 let has_available_code_actions = editor_value.has_available_code_actions_for_selection();
138 let code_action_enabled = editor_value.code_actions_enabled_for_toolbar(cx);
139 let focus_handle = editor_value.focus_handle(cx);
140
141 let search_button = (editor.buffer_kind(cx) == ItemBufferKind::Singleton).then(|| {
142 QuickActionBarButton::new(
143 "toggle buffer search",
144 search::SEARCH_ICON,
145 !self.buffer_search_bar.read(cx).is_dismissed(),
146 Box::new(buffer_search::Deploy::find()),
147 focus_handle.clone(),
148 "Buffer Search",
149 {
150 let buffer_search_bar = self.buffer_search_bar.clone();
151 move |_, window, cx| {
152 buffer_search_bar.update(cx, |search_bar, cx| {
153 search_bar.toggle(&buffer_search::Deploy::find(), window, cx)
154 });
155 }
156 },
157 )
158 });
159
160 let assistant_button = QuickActionBarButton::new(
161 "toggle inline assistant",
162 IconName::OmegaAssistant,
163 false,
164 Box::new(InlineAssist::default()),
165 focus_handle,
166 "Inline Assist",
167 move |_, window, cx| {
168 window.dispatch_action(Box::new(InlineAssist::default()), cx);
169 },
170 );
171
172 let code_actions_dropdown = code_action_enabled.then(|| {
173 let is_deployed = {
174 let menu_ref = editor.read(cx).context_menu().borrow();
175 let code_action_menu = menu_ref
176 .as_ref()
177 .filter(|menu| matches!(menu, CodeContextMenu::CodeActions(..)));
178 code_action_menu
179 .as_ref()
180 .is_some_and(|menu| matches!(menu.origin(), ContextMenuOrigin::QuickActionBar))
181 };
182 let code_action_element = is_deployed
183 .then(|| {
184 editor.update(cx, |editor, cx| {
185 editor.render_context_menu(MAX_CODE_ACTION_MENU_LINES, window, cx)
186 })
187 })
188 .flatten();
189 v_flex()
190 .child(
191 IconButton::new("toggle_code_actions_icon", IconName::BoltOutlined)
192 .icon_size(IconSize::Small)
193 .style(ButtonStyle::Subtle)
194 .disabled(!has_available_code_actions)
195 .toggle_state(is_deployed)
196 .when(!is_deployed, |this| {
197 this.when(has_available_code_actions, |this| {
198 this.tooltip(Tooltip::for_action_title(
199 "Code Actions",
200 &ToggleCodeActions::default(),
201 ))
202 })
203 .when(
204 !has_available_code_actions,
205 |this| {
206 this.tooltip(Tooltip::for_action_title(
207 "No Code Actions Available",
208 &ToggleCodeActions::default(),
209 ))
210 },
211 )
212 })
213 .on_click({
214 let editor = editor.clone();
215 move |_, window, cx| {
216 editor.update(cx, |editor, cx| {
217 editor.toggle_code_actions(
218 &ToggleCodeActions {
219 deployed_from: Some(CodeActionSource::QuickActionBar),
220 quick_launch: false,
221 },
222 window,
223 cx,
224 );
225 })
226 }
227 }),
228 )
229 .children(code_action_element.map(|menu| {
230 deferred(
231 anchored()
232 .position_mode(AnchoredPositionMode::Local)
233 .position(point(px(20.), px(20.)))
234 .anchor(Anchor::TopRight)
235 .child(menu),
236 )
237 }))
238 });
239
240 let editor_selections_dropdown = selection_menu_enabled.then(|| {
241 let has_diff_hunks = editor
242 .read(cx)
243 .buffer()
244 .read(cx)
245 .snapshot(cx)
246 .has_diff_hunks();
247 let has_selection = editor.update(cx, |editor, cx| {
248 editor.has_non_empty_selection(&editor.display_snapshot(cx))
249 });
250
251 let focus = editor.focus_handle(cx);
252
253 let disable_ai = DisableAiSettings::get_global(cx).disable_ai;
254
255 PopoverMenu::new("editor-selections-dropdown")
256 .trigger_with_tooltip(
257 IconButton::new("toggle_editor_selections_icon", IconName::CursorIBeam)
258 .icon_size(IconSize::Small)
259 .style(ButtonStyle::Subtle)
260 .toggle_state(self.toggle_selections_handle.is_deployed()),
261 Tooltip::text("Selection Controls"),
262 )
263 .with_handle(self.toggle_selections_handle.clone())
264 .anchor(Anchor::TopRight)
265 .menu(move |window, cx| {
266 let focus = focus.clone();
267 let menu = ContextMenu::build(window, cx, move |menu, _, _| {
268 menu.context(focus.clone())
269 .action("Select All", Box::new(SelectAll))
270 .action(
271 "Select Next Occurrence",
272 Box::new(SelectNext {
273 replace_newest: false,
274 }),
275 )
276 .action("Expand Selection", Box::new(SelectLargerSyntaxNode))
277 .action("Shrink Selection", Box::new(SelectSmallerSyntaxNode))
278 .action(
279 "Add Cursor Above",
280 Box::new(AddSelectionAbove {
281 skip_soft_wrap: true,
282 }),
283 )
284 .action(
285 "Add Cursor Below",
286 Box::new(AddSelectionBelow {
287 skip_soft_wrap: true,
288 }),
289 )
290 .when(!disable_ai, |this| {
291 this.separator().action_disabled_when(
292 !has_selection,
293 "Add to Agent Thread",
294 Box::new(AddSelectionToThread),
295 )
296 })
297 .separator()
298 .action("Go to Symbol", Box::new(ToggleOutline))
299 .action("Go to Line/Column", Box::new(ToggleGoToLine))
300 .separator()
301 .action("Next Problem", Box::new(GoToDiagnostic::default()))
302 .action(
303 "Previous Problem",
304 Box::new(GoToPreviousDiagnostic::default()),
305 )
306 .separator()
307 .action_disabled_when(!has_diff_hunks, "Next Hunk", Box::new(GoToHunk))
308 .action_disabled_when(
309 !has_diff_hunks,
310 "Previous Hunk",
311 Box::new(GoToPreviousHunk),
312 )
313 .separator()
314 .action("Move Line Up", Box::new(MoveLineUp))
315 .action("Move Line Down", Box::new(MoveLineDown))
316 .action("Duplicate Selection", Box::new(DuplicateLineDown))
317 });
318 Some(menu)
319 })
320 });
321
322 let editor_focus_handle = editor.focus_handle(cx);
323 let editor = editor.downgrade();
324 let editor_settings_dropdown = {
325 let vim_mode_enabled = VimModeSetting::get_global(cx).0;
326 let helix_mode_enabled = HelixModeSetting::get_global(cx).0;
327
328 PopoverMenu::new("editor-settings")
329 .trigger_with_tooltip(
330 IconButton::new("toggle_editor_settings_icon", IconName::Filter)
331 .icon_size(IconSize::Small)
332 .toggle_state(self.toggle_settings_handle.is_deployed()),
333 Tooltip::text("Editor Controls"),
334 )
335 .anchor(Anchor::TopRight)
336 .with_handle(self.toggle_settings_handle.clone())
337 .menu(move |window, cx| {
338 let menu = ContextMenu::build(window, cx, {
339 let focus_handle = editor_focus_handle.clone();
340 |mut menu, _, _| {
341 menu = menu.context(focus_handle);
342
343 if supports_inlay_hints {
344 menu = menu.toggleable_entry(
345 "Inlay Hints",
346 inlay_hints_enabled,
347 IconPosition::Start,
348 Some(editor::actions::ToggleInlayHints.boxed_clone()),
349 {
350 let editor = editor.clone();
351 move |window, cx| {
352 editor
353 .update(cx, |editor, cx| {
354 editor.toggle_inlay_hints(
355 &editor::actions::ToggleInlayHints,
356 window,
357 cx,
358 );
359 })
360 .ok();
361 }
362 },
363 );
364
365 menu = menu.toggleable_entry(
366 "Inline Values",
367 inline_values_enabled,
368 IconPosition::Start,
369 Some(editor::actions::ToggleInlineValues.boxed_clone()),
370 {
371 let editor = editor.clone();
372 move |window, cx| {
373 editor
374 .update(cx, |editor, cx| {
375 editor.toggle_inline_values(
376 &editor::actions::ToggleInlineValues,
377 window,
378 cx,
379 );
380 })
381 .ok();
382 }
383 }
384 );
385 }
386
387 if supports_semantic_tokens {
388 menu = menu.toggleable_entry(
389 "Semantic Highlights",
390 semantic_highlights_enabled,
391 IconPosition::Start,
392 Some(editor::actions::ToggleSemanticHighlights.boxed_clone()),
393 {
394 let editor = editor.clone();
395 move |window, cx| {
396 editor
397 .update(cx, |editor, cx| {
398 editor.toggle_semantic_highlights(
399 &editor::actions::ToggleSemanticHighlights,
400 window,
401 cx,
402 );
403 })
404 .ok();
405 }
406 },
407 );
408 }
409
410 if supports_code_lens {
411 menu = menu.toggleable_entry(
412 "Code Lens",
413 code_lens_enabled,
414 IconPosition::Start,
415 Some(editor::actions::ToggleCodeLens.boxed_clone()),
416 {
417 let editor = editor.clone();
418 move |window, cx| {
419 editor
420 .update(cx, |editor, cx| {
421 editor.toggle_code_lens_action(
422 &editor::actions::ToggleCodeLens,
423 window,
424 cx,
425 );
426 })
427 .ok();
428 }
429 },
430 );
431 }
432
433 if supports_minimap {
434 menu = menu.toggleable_entry("Minimap", minimap_enabled, IconPosition::Start, Some(editor::actions::ToggleMinimap.boxed_clone()), {
435 let editor = editor.clone();
436 move |window, cx| {
437 editor
438 .update(cx, |editor, cx| {
439 editor.toggle_minimap(
440 &editor::actions::ToggleMinimap,
441 window,
442 cx,
443 );
444 })
445 .ok();
446 }
447 },)
448 }
449
450 if has_edit_prediction_provider {
451 let mut edit_prediction_entry = ContextMenuEntry::new("Edit Predictions")
452 .toggleable(IconPosition::Start, edit_predictions_enabled_at_cursor && show_edit_predictions)
453 .disabled(!edit_predictions_enabled_at_cursor)
454 .action(
455 editor::actions::ToggleEditPrediction.boxed_clone(),
456 ).handler({
457 let editor = editor.clone();
458 move |window, cx| {
459 editor
460 .update(cx, |editor, cx| {
461 editor.toggle_edit_predictions(
462 &editor::actions::ToggleEditPrediction,
463 window,
464 cx,
465 );
466 })
467 .ok();
468 }
469 });
470 if !edit_predictions_enabled_at_cursor {
471 edit_prediction_entry = edit_prediction_entry.documentation_aside(DocumentationSide::Left, |_| {
472 Label::new("You can't toggle edit predictions for this file as it is within the excluded files list.").into_any_element()
473 });
474 }
475
476 menu = menu.item(edit_prediction_entry);
477 }
478
479 menu = menu.separator();
480
481 if is_full {
482 menu = menu.toggleable_entry(
483 "Diagnostics",
484 diagnostics_enabled,
485 IconPosition::Start,
486 Some(ToggleDiagnostics.boxed_clone()),
487 {
488 let editor = editor.clone();
489 move |window, cx| {
490 editor
491 .update(cx, |editor, cx| {
492 editor.toggle_diagnostics(
493 &ToggleDiagnostics,
494 window,
495 cx,
496 );
497 })
498 .ok();
499 }
500 },
501 );
502
503 if supports_inline_diagnostics {
504 let mut inline_diagnostics_item = ContextMenuEntry::new("Inline Diagnostics")
505 .toggleable(IconPosition::Start, diagnostics_enabled && inline_diagnostics_enabled)
506 .action(ToggleInlineDiagnostics.boxed_clone())
507 .handler({
508 let editor = editor.clone();
509 move |window, cx| {
510 editor
511 .update(cx, |editor, cx| {
512 editor.toggle_inline_diagnostics(
513 &ToggleInlineDiagnostics,
514 window,
515 cx,
516 );
517 })
518 .ok();
519 }
520 });
521 if !diagnostics_enabled {
522 inline_diagnostics_item = inline_diagnostics_item.disabled(true).documentation_aside(DocumentationSide::Left, |_| Label::new("Inline diagnostics are not available until regular diagnostics are enabled.").into_any_element());
523 }
524 menu = menu.item(inline_diagnostics_item)
525 }
526
527 menu = menu.separator();
528 }
529
530 menu = menu.toggleable_entry(
531 "Line Numbers",
532 show_line_numbers,
533 IconPosition::Start,
534 Some(editor::actions::ToggleLineNumbers.boxed_clone()),
535 {
536 let editor = editor.clone();
537 move |window, cx| {
538 editor
539 .update(cx, |editor, cx| {
540 editor.toggle_line_numbers(
541 &editor::actions::ToggleLineNumbers,
542 window,
543 cx,
544 );
545 })
546 .ok();
547 }
548 },
549 );
550
551 menu = menu.toggleable_entry(
552 "Selection Menu",
553 selection_menu_enabled,
554 IconPosition::Start,
555 Some(editor::actions::ToggleSelectionMenu.boxed_clone()),
556 {
557 let editor = editor.clone();
558 move |window, cx| {
559 editor
560 .update(cx, |editor, cx| {
561 editor.toggle_selection_menu(
562 &editor::actions::ToggleSelectionMenu,
563 window,
564 cx,
565 )
566 })
567 .ok();
568 }
569 },
570 );
571
572 menu = menu.toggleable_entry(
573 "Auto Signature Help",
574 auto_signature_help_enabled,
575 IconPosition::Start,
576 Some(editor::actions::ToggleAutoSignatureHelp.boxed_clone()),
577 {
578 let editor = editor.clone();
579 move |window, cx| {
580 editor
581 .update(cx, |editor, cx| {
582 editor.toggle_auto_signature_help_menu(
583 &editor::actions::ToggleAutoSignatureHelp,
584 window,
585 cx,
586 );
587 })
588 .ok();
589 }
590 },
591 );
592
593 menu = menu.separator();
594
595 menu = menu.toggleable_entry(
596 "Inline Git Blame",
597 git_blame_inline_enabled,
598 IconPosition::Start,
599 Some(editor::actions::ToggleGitBlameInline.boxed_clone()),
600 {
601 let editor = editor.clone();
602 move |window, cx| {
603 editor
604 .update(cx, |editor, cx| {
605 editor.toggle_git_blame_inline(
606 &editor::actions::ToggleGitBlameInline,
607 window,
608 cx,
609 )
610 })
611 .ok();
612 }
613 },
614 );
615
616 menu = menu.toggleable_entry(
617 "Column Git Blame",
618 show_git_blame_gutter,
619 IconPosition::Start,
620 Some(git::Blame.boxed_clone()),
621 {
622 let editor = editor.clone();
623 move |window, cx| {
624 editor
625 .update(cx, |editor, cx| {
626 editor.toggle_git_blame(
627 &git::Blame,
628 window,
629 cx,
630 )
631 })
632 .ok();
633 }
634 },
635 );
636
637 menu = menu.separator();
638
639 menu = menu.toggleable_entry(
640 "Vim Mode",
641 vim_mode_enabled,
642 IconPosition::Start,
643 None,
644 {
645 move |window, cx| {
646 let new_value = !vim_mode_enabled;
647 VimModeSetting::override_global(VimModeSetting(new_value), cx);
648 HelixModeSetting::override_global(HelixModeSetting(false), cx);
649 window.refresh();
650 }
651 },
652 );
653 menu = menu.toggleable_entry(
654 "Helix Mode",
655 helix_mode_enabled,
656 IconPosition::Start,
657 None,
658 {
659 move |window, cx| {
660 let new_value = !helix_mode_enabled;
661 HelixModeSetting::override_global(HelixModeSetting(new_value), cx);
662 VimModeSetting::override_global(VimModeSetting(false), cx);
663 window.refresh();
664 }
665 }
666 );
667
668 menu
669 }
670 });
671 Some(menu)
672 })
673 };
674
675 h_flex()
676 .id("quick action bar")
677 .gap(DynamicSpacing::Base01.rems(cx))
678 .children(self.render_repl_menu(cx))
679 .children(self.render_preview_button(cx))
680 .children(search_button)
681 .when(
682 AgentSettings::get_global(cx).enabled(cx) && AgentSettings::get_global(cx).button,
683 |bar| bar.child(assistant_button),
684 )
685 .children(code_actions_dropdown)
686 .children(editor_selections_dropdown)
687 .child(editor_settings_dropdown)
688 }
689}
690
691impl EventEmitter<ToolbarItemEvent> for QuickActionBar {}
692
693#[derive(IntoElement)]
694struct QuickActionBarButton {
695 id: ElementId,
696 icon: IconName,
697 toggled: bool,
698 action: Box<dyn Action>,
699 focus_handle: FocusHandle,
700 tooltip: SharedString,
701 on_click: Box<dyn Fn(&ClickEvent, &mut Window, &mut App)>,
702}
703
704impl QuickActionBarButton {
705 fn new(
706 id: impl Into<ElementId>,
707 icon: IconName,
708 toggled: bool,
709 action: Box<dyn Action>,
710 focus_handle: FocusHandle,
711 tooltip: impl Into<SharedString>,
712 on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
713 ) -> Self {
714 Self {
715 id: id.into(),
716 icon,
717 toggled,
718 action,
719 focus_handle,
720 tooltip: tooltip.into(),
721 on_click: Box::new(on_click),
722 }
723 }
724}
725
726impl RenderOnce for QuickActionBarButton {
727 fn render(self, _window: &mut Window, _: &mut App) -> impl IntoElement {
728 let tooltip = self.tooltip.clone();
729 let action = self.action.boxed_clone();
730
731 IconButton::new(self.id.clone(), self.icon)
732 .icon_size(IconSize::Small)
733 .style(ButtonStyle::Subtle)
734 .toggle_state(self.toggled)
735 .tooltip(move |_window, cx| {
736 Tooltip::for_action_in(tooltip.clone(), &*action, &self.focus_handle, cx)
737 })
738 .on_click(move |event, window, cx| (self.on_click)(event, window, cx))
739 }
740}
741
742impl ToolbarItemView for QuickActionBar {
743 fn set_active_pane_item(
744 &mut self,
745 active_pane_item: Option<&dyn ItemHandle>,
746 _: &mut Window,
747 cx: &mut Context<Self>,
748 ) -> ToolbarItemLocation {
749 self.active_item = active_pane_item.map(ItemHandle::boxed_clone);
750 if let Some(active_item) = active_pane_item {
751 self._inlay_hints_enabled_subscription.take();
752
753 if let Some(editor) = active_item.downcast::<Editor>() {
754 let (
755 mut inlay_hints_enabled,
756 mut supports_inlay_hints,
757 mut supports_semantic_tokens,
758 ) = editor.update(cx, |editor, cx| {
759 (
760 editor.inlay_hints_enabled(),
761 editor.supports_inlay_hints(cx),
762 editor.supports_semantic_tokens(cx),
763 )
764 });
765 self._inlay_hints_enabled_subscription =
766 Some(cx.observe(&editor, move |_, editor, cx| {
767 let (
768 new_inlay_hints_enabled,
769 new_supports_inlay_hints,
770 new_supports_semantic_tokens,
771 ) = editor.update(cx, |editor, cx| {
772 (
773 editor.inlay_hints_enabled(),
774 editor.supports_inlay_hints(cx),
775 editor.supports_semantic_tokens(cx),
776 )
777 });
778 let should_notify = inlay_hints_enabled != new_inlay_hints_enabled
779 || supports_inlay_hints != new_supports_inlay_hints
780 || supports_semantic_tokens != new_supports_semantic_tokens;
781 inlay_hints_enabled = new_inlay_hints_enabled;
782 supports_inlay_hints = new_supports_inlay_hints;
783 supports_semantic_tokens = new_supports_semantic_tokens;
784 if should_notify {
785 cx.notify()
786 }
787 }));
788 }
789 }
790 self.get_toolbar_item_location()
791 }
792}
793