Detailed changes
@@ -2486,7 +2486,6 @@ dependencies = [
"postage",
"project",
"regex",
- "search",
"serde",
"serde_derive",
"settings",
@@ -7762,6 +7761,7 @@ dependencies = [
"procinfo",
"project",
"rand 0.8.5",
+ "search",
"serde",
"serde_derive",
"settings",
@@ -38,7 +38,7 @@ use gpui::{
};
use language::{language_settings::SoftWrap, Buffer, LanguageRegistry, ToOffset as _};
use project::Project;
-use search::BufferSearchBar;
+use search::{buffer_search::DivRegistrar, BufferSearchBar};
use semantic_index::{SemanticIndex, SemanticIndexStatus};
use settings::{Settings, SettingsStore};
use std::{
@@ -1156,6 +1156,16 @@ impl Render for AssistantPanel {
div()
});
+ let contents = if self.active_editor().is_some() {
+ let mut registrar = DivRegistrar::new(
+ |panel, cx| panel.toolbar.read(cx).item_of_type::<BufferSearchBar>(),
+ cx,
+ );
+ BufferSearchBar::register_inner(&mut registrar);
+ registrar.into_div()
+ } else {
+ div()
+ };
v_stack()
.key_context("AssistantPanel")
.size_full()
@@ -1176,7 +1186,7 @@ impl Render for AssistantPanel {
Some(self.toolbar.clone())
})
.child(
- div()
+ contents
.flex_1()
.child(if let Some(editor) = self.active_editor() {
editor.clone().into_any_element()
@@ -11,15 +11,16 @@ use channel::{Channel, ChannelEvent, ChannelId, ChannelStore};
use client::{Client, Contact, User, UserStore};
use contact_finder::ContactFinder;
use db::kvp::KEY_VALUE_STORE;
-use editor::Editor;
+use editor::{Editor, EditorElement, EditorStyle};
use feature_flags::{ChannelsAlpha, FeatureFlagAppExt, FeatureFlagViewExt};
use fuzzy::{match_strings, StringMatchCandidate};
use gpui::{
actions, canvas, div, fill, list, overlay, point, prelude::*, px, serde_json, AnyElement,
AppContext, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent, Div, EventEmitter,
- FocusHandle, FocusableView, InteractiveElement, IntoElement, ListOffset, ListState, Model,
- MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Render, RenderOnce, SharedString,
- Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView,
+ FocusHandle, FocusableView, FontStyle, FontWeight, InteractiveElement, IntoElement, ListOffset,
+ ListState, Model, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Render,
+ RenderOnce, SharedString, Styled, Subscription, Task, TextStyle, View, ViewContext,
+ VisualContext, WeakView, WhiteSpace,
};
use menu::{Cancel, Confirm, SelectNext, SelectPrev};
use project::{Fs, Project};
@@ -29,10 +30,9 @@ use settings::{Settings, SettingsStore};
use smallvec::SmallVec;
use std::{mem, sync::Arc};
use theme::{ActiveTheme, ThemeSettings};
-use ui::prelude::*;
use ui::{
- h_stack, v_stack, Avatar, Button, Color, ContextMenu, Icon, IconButton, IconElement, IconSize,
- Label, ListHeader, ListItem, Tooltip,
+ prelude::*, Avatar, Button, Color, ContextMenu, Icon, IconButton, IconElement, IconSize, Label,
+ ListHeader, ListItem, Tooltip,
};
use util::{maybe, ResultExt, TryFutureExt};
use workspace::{
@@ -1749,15 +1749,49 @@ impl CollabPanel {
.size_full()
.child(list(self.list_state.clone()).full())
.child(
- v_stack().p_2().child(
- v_stack()
- .border_primary(cx)
- .border_t()
- .child(self.filter_editor.clone()),
- ),
+ v_stack()
+ .child(div().mx_2().border_primary(cx).border_t())
+ .child(
+ v_stack()
+ .p_2()
+ .child(self.render_filter_input(&self.filter_editor, cx)),
+ ),
)
}
+ fn render_filter_input(
+ &self,
+ editor: &View<Editor>,
+ cx: &mut ViewContext<Self>,
+ ) -> impl IntoElement {
+ let settings = ThemeSettings::get_global(cx);
+ let text_style = TextStyle {
+ color: if editor.read(cx).read_only() {
+ cx.theme().colors().text_disabled
+ } else {
+ cx.theme().colors().text
+ },
+ font_family: settings.ui_font.family.clone(),
+ font_features: settings.ui_font.features,
+ font_size: rems(0.875).into(),
+ font_weight: FontWeight::NORMAL,
+ font_style: FontStyle::Normal,
+ line_height: relative(1.3).into(),
+ background_color: None,
+ underline: None,
+ white_space: WhiteSpace::Normal,
+ };
+
+ EditorElement::new(
+ editor,
+ EditorStyle {
+ local_player: cx.theme().players().local(),
+ text: text_style,
+ ..Default::default()
+ },
+ )
+ }
+
fn render_header(
&self,
section: Section,
@@ -641,8 +641,13 @@ impl Item for ProjectDiagnosticsEditor {
fn tab_content(&self, _detail: Option<usize>, selected: bool, _: &WindowContext) -> AnyElement {
if self.summary.error_count == 0 && self.summary.warning_count == 0 {
- let label = Label::new("No problems");
- label.into_any_element()
+ Label::new("No problems")
+ .color(if selected {
+ Color::Default
+ } else {
+ Color::Muted
+ })
+ .into_any_element()
} else {
h_stack()
.gap_1()
@@ -18,7 +18,6 @@ gpui = { path = "../gpui" }
language = { path = "../language" }
menu = { path = "../menu" }
project = { path = "../project" }
-search = { path = "../search" }
settings = { path = "../settings" }
theme = { path = "../theme" }
ui = { path = "../ui" }
@@ -10,7 +10,7 @@ use language::{LanguageServerId, LanguageServerName};
use lsp::IoKind;
use project::{search::SearchQuery, Project};
use std::{borrow::Cow, sync::Arc};
-use ui::{h_stack, popover_menu, Button, Checkbox, Clickable, ContextMenu, Label, Selection};
+use ui::{popover_menu, prelude::*, Button, Checkbox, ContextMenu, Label, Selection};
use workspace::{
item::{Item, ItemHandle},
searchable::{SearchEvent, SearchableItem, SearchableItemHandle},
@@ -614,8 +614,14 @@ impl Item for LspLogView {
Editor::to_item_events(event, f)
}
- fn tab_content(&self, _: Option<usize>, _: bool, _: &WindowContext<'_>) -> AnyElement {
- Label::new("LSP Logs").into_any_element()
+ fn tab_content(&self, _: Option<usize>, selected: bool, _: &WindowContext<'_>) -> AnyElement {
+ Label::new("LSP Logs")
+ .color(if selected {
+ Color::Default
+ } else {
+ Color::Muted
+ })
+ .into_any_element()
}
fn as_searchable(&self, handle: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
@@ -405,8 +405,14 @@ impl Item for SyntaxTreeView {
fn to_item_events(_: &Self::Event, _: impl FnMut(workspace::item::ItemEvent)) {}
- fn tab_content(&self, _: Option<usize>, _: bool, _: &WindowContext<'_>) -> AnyElement {
- Label::new("Syntax Tree").into_any_element()
+ fn tab_content(&self, _: Option<usize>, selected: bool, _: &WindowContext<'_>) -> AnyElement {
+ Label::new("Syntax Tree")
+ .color(if selected {
+ Color::Default
+ } else {
+ Color::Muted
+ })
+ .into_any_element()
}
fn clone_on_split(
@@ -1395,7 +1395,7 @@ impl ProjectPanel {
.child(if let Some(icon) = &icon {
div().child(IconElement::from_path(icon.to_string()).color(Color::Muted))
} else {
- div()
+ div().size(IconSize::default().rems()).invisible()
})
.child(
if let (Some(editor), true) = (Some(&self.filename_editor), show_editor) {
@@ -422,89 +422,134 @@ impl ToolbarItemView for BufferSearchBar {
}
}
-impl BufferSearchBar {
- fn register(workspace: &mut Workspace) {
- workspace.register_action(move |workspace, deploy: &Deploy, cx| {
- let pane = workspace.active_pane();
+/// Registrar inverts the dependency between search and it's downstream user, allowing said downstream user to register search action without knowing exactly what those actions are.
+pub trait SearchActionsRegistrar {
+ fn register_handler<A: Action>(
+ &mut self,
+ callback: fn(&mut BufferSearchBar, &A, &mut ViewContext<BufferSearchBar>),
+ );
+}
+
+type GetSearchBar<T> =
+ for<'a, 'b> fn(&'a T, &'a mut ViewContext<'b, T>) -> Option<View<BufferSearchBar>>;
+
+/// Registers search actions on a div that can be taken out.
+pub struct DivRegistrar<'a, 'b, T: 'static> {
+ div: Option<Div>,
+ cx: &'a mut ViewContext<'b, T>,
+ search_getter: GetSearchBar<T>,
+}
+
+impl<'a, 'b, T: 'static> DivRegistrar<'a, 'b, T> {
+ pub fn new(search_getter: GetSearchBar<T>, cx: &'a mut ViewContext<'b, T>) -> Self {
+ Self {
+ div: Some(div()),
+ cx,
+ search_getter,
+ }
+ }
+ pub fn into_div(self) -> Div {
+ // This option is always Some; it's an option in the first place because we want to call methods
+ // on div that require ownership.
+ self.div.unwrap()
+ }
+}
+
+impl<T: 'static> SearchActionsRegistrar for DivRegistrar<'_, '_, T> {
+ fn register_handler<A: gpui::Action>(
+ &mut self,
+ callback: fn(&mut BufferSearchBar, &A, &mut ViewContext<BufferSearchBar>),
+ ) {
+ let getter = self.search_getter;
+ self.div = self.div.take().map(|div| {
+ div.on_action(self.cx.listener(move |this, action, cx| {
+ (getter)(this, cx)
+ .clone()
+ .map(|search_bar| search_bar.update(cx, |this, cx| callback(this, action, cx)));
+ }))
+ });
+ }
+}
- pane.update(cx, |this, cx| {
- this.toolbar().update(cx, |this, cx| {
+/// Register actions for an active pane.
+impl SearchActionsRegistrar for Workspace {
+ fn register_handler<A: Action>(
+ &mut self,
+ callback: fn(&mut BufferSearchBar, &A, &mut ViewContext<BufferSearchBar>),
+ ) {
+ self.register_action(move |workspace, action: &A, cx| {
+ let pane = workspace.active_pane();
+ pane.update(cx, move |this, cx| {
+ this.toolbar().update(cx, move |this, cx| {
if let Some(search_bar) = this.item_of_type::<BufferSearchBar>() {
- search_bar.update(cx, |this, cx| {
- this.deploy(deploy, cx);
- });
- return;
+ search_bar.update(cx, move |this, cx| callback(this, action, cx));
+ cx.notify();
}
- let view = cx.new_view(|cx| BufferSearchBar::new(cx));
- this.add_item(view.clone(), cx);
- view.update(cx, |this, cx| this.deploy(deploy, cx));
- cx.notify();
})
});
});
- fn register_action<A: Action>(
- workspace: &mut Workspace,
- update: fn(&mut BufferSearchBar, &A, &mut ViewContext<BufferSearchBar>),
- ) {
- workspace.register_action(move |workspace, action: &A, cx| {
- let pane = workspace.active_pane();
- pane.update(cx, move |this, cx| {
- this.toolbar().update(cx, move |this, cx| {
- if let Some(search_bar) = this.item_of_type::<BufferSearchBar>() {
- search_bar.update(cx, move |this, cx| update(this, action, cx));
- cx.notify();
- }
- })
- });
- });
- }
-
- register_action(workspace, |this, action: &ToggleCaseSensitive, cx| {
+ }
+}
+impl BufferSearchBar {
+ pub fn register_inner(registrar: &mut impl SearchActionsRegistrar) {
+ registrar.register_handler(|this, action: &ToggleCaseSensitive, cx| {
if this.supported_options().case {
this.toggle_case_sensitive(action, cx);
}
});
- register_action(workspace, |this, action: &ToggleWholeWord, cx| {
+
+ registrar.register_handler(|this, action: &ToggleWholeWord, cx| {
if this.supported_options().word {
this.toggle_whole_word(action, cx);
}
});
- register_action(workspace, |this, action: &ToggleReplace, cx| {
+
+ registrar.register_handler(|this, action: &ToggleReplace, cx| {
if this.supported_options().replacement {
this.toggle_replace(action, cx);
}
});
- register_action(workspace, |this, _: &ActivateRegexMode, cx| {
+
+ registrar.register_handler(|this, _: &ActivateRegexMode, cx| {
if this.supported_options().regex {
this.activate_search_mode(SearchMode::Regex, cx);
}
});
- register_action(workspace, |this, _: &ActivateTextMode, cx| {
+
+ registrar.register_handler(|this, _: &ActivateTextMode, cx| {
this.activate_search_mode(SearchMode::Text, cx);
});
- register_action(workspace, |this, action: &CycleMode, cx| {
+
+ registrar.register_handler(|this, action: &CycleMode, cx| {
if this.supported_options().regex {
// If regex is not supported then search has just one mode (text) - in that case there's no point in supporting
// cycling.
this.cycle_mode(action, cx)
}
});
- register_action(workspace, |this, action: &SelectNextMatch, cx| {
+
+ registrar.register_handler(|this, action: &SelectNextMatch, cx| {
this.select_next_match(action, cx);
});
- register_action(workspace, |this, action: &SelectPrevMatch, cx| {
+ registrar.register_handler(|this, action: &SelectPrevMatch, cx| {
this.select_prev_match(action, cx);
});
- register_action(workspace, |this, action: &SelectAllMatches, cx| {
+ registrar.register_handler(|this, action: &SelectAllMatches, cx| {
this.select_all_matches(action, cx);
});
- register_action(workspace, |this, _: &editor::Cancel, cx| {
+ registrar.register_handler(|this, _: &editor::Cancel, cx| {
if !this.dismissed {
this.dismiss(&Dismiss, cx);
return;
}
cx.propagate();
});
+ registrar.register_handler(|this, deploy, cx| {
+ this.deploy(deploy, cx);
+ })
+ }
+ fn register(workspace: &mut Workspace) {
+ Self::register_inner(workspace);
}
pub fn new(cx: &mut ViewContext<Self>) -> Self {
let query_editor = cx.new_view(|cx| Editor::single_line(cx));
@@ -158,39 +158,41 @@ pub fn mouse_moved_report(point: AlacPoint, e: &MouseMoveEvent, mode: TermMode)
}
}
-pub fn mouse_side(
+pub fn grid_point(pos: Point<Pixels>, cur_size: TerminalSize, display_offset: usize) -> AlacPoint {
+ grid_point_and_side(pos, cur_size, display_offset).0
+}
+
+pub fn grid_point_and_side(
pos: Point<Pixels>,
cur_size: TerminalSize,
-) -> alacritty_terminal::index::Direction {
- let cell_width = cur_size.cell_width.floor();
- if cell_width == px(0.) {
- return Side::Right;
- }
-
- let x = pos.x.floor();
-
- let cell_x = cmp::max(px(0.), x - cell_width) % cell_width;
- let half_cell_width = (cur_size.cell_width / 2.0).floor();
- let additional_padding = (cur_size.width() - cur_size.cell_width * 2.) % cur_size.cell_width;
- let end_of_grid = cur_size.width() - cur_size.cell_width - additional_padding;
-
- //Width: Pixels or columns?
- if cell_x > half_cell_width
- // Edge case when mouse leaves the window.
- || x >= end_of_grid
- {
+ display_offset: usize,
+) -> (AlacPoint, Side) {
+ let mut col = GridCol((pos.x / cur_size.cell_width) as usize);
+ let cell_x = cmp::max(px(0.), pos.x) % cur_size.cell_width;
+ let half_cell_width = cur_size.cell_width / 2.0;
+ let mut side = if cell_x > half_cell_width {
Side::Right
} else {
Side::Left
- }
-}
+ };
-pub fn grid_point(pos: Point<Pixels>, cur_size: TerminalSize, display_offset: usize) -> AlacPoint {
- let col = GridCol((pos.x / cur_size.cell_width) as usize);
+ if col > cur_size.last_column() {
+ col = cur_size.last_column();
+ side = Side::Right;
+ }
let col = min(col, cur_size.last_column());
- let line = (pos.y / cur_size.line_height) as i32;
- let line = min(line, cur_size.bottommost_line().0);
- AlacPoint::new(GridLine(line - display_offset as i32), col)
+ let mut line = (pos.y / cur_size.line_height) as i32;
+ if line > cur_size.bottommost_line() {
+ line = cur_size.bottommost_line().0 as i32;
+ side = Side::Right;
+ } else if line < 0 {
+ side = Side::Left;
+ }
+
+ (
+ AlacPoint::new(GridLine(line - display_offset as i32), col),
+ side,
+ )
}
///Generate the bytes to send to the terminal, from the cell location, a mouse event, and the terminal mode
@@ -28,7 +28,8 @@ use futures::{
};
use mappings::mouse::{
- alt_scroll, grid_point, mouse_button_report, mouse_moved_report, mouse_side, scroll_report,
+ alt_scroll, grid_point, grid_point_and_side, mouse_button_report, mouse_moved_report,
+ scroll_report,
};
use procinfo::LocalProcessInfo;
@@ -704,14 +705,12 @@ impl Terminal {
}
InternalEvent::UpdateSelection(position) => {
if let Some(mut selection) = term.selection.take() {
- let point = grid_point(
+ let (point, side) = grid_point_and_side(
*position,
self.last_content.size,
term.grid().display_offset(),
);
- let side = mouse_side(*position, self.last_content.size);
-
selection.update(point, side);
term.selection = Some(selection);
@@ -1088,12 +1087,11 @@ impl Terminal {
let position = e.position - origin;
self.last_mouse_position = Some(position);
if self.mouse_mode(e.modifiers.shift) {
- let point = grid_point(
+ let (point, side) = grid_point_and_side(
position,
self.last_content.size,
self.last_content.display_offset,
);
- let side = mouse_side(position, self.last_content.size);
if self.mouse_changed(point, side) {
if let Some(bytes) = mouse_moved_report(point, e, self.last_content.mode) {
@@ -1175,15 +1173,12 @@ impl Terminal {
}
} else if e.button == MouseButton::Left {
let position = e.position - origin;
- let point = grid_point(
+ let (point, side) = grid_point_and_side(
position,
self.last_content.size,
self.last_content.display_offset,
);
- // Use .opposite so that selection is inclusive of the cell clicked.
- let side = mouse_side(position, self.last_content.size);
-
let selection_type = match e.click_count {
0 => return, //This is a release
1 => Some(SelectionType::Simple),
@@ -13,7 +13,7 @@ editor = { path = "../editor" }
language = { path = "../language" }
gpui = { path = "../gpui" }
project = { path = "../project" }
-# search = { path = "../search" }
+search = { path = "../search" }
settings = { path = "../settings" }
theme = { path = "../theme" }
util = { path = "../util" }
@@ -2,10 +2,11 @@ use editor::{Cursor, HighlightedRange, HighlightedRangeLine};
use gpui::{
div, fill, point, px, red, relative, AnyElement, AsyncWindowContext, AvailableSpace,
BorrowWindow, Bounds, DispatchPhase, Element, ElementId, ExternalPaths, FocusHandle, Font,
- FontStyle, FontWeight, HighlightStyle, Hsla, InteractiveElement, InteractiveElementState,
- Interactivity, IntoElement, LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton,
- Pixels, PlatformInputHandler, Point, ShapedLine, StatefulInteractiveElement, StyleRefinement,
- Styled, TextRun, TextStyle, TextSystem, UnderlineStyle, WhiteSpace, WindowContext,
+ FontStyle, FontWeight, HighlightStyle, Hsla, InteractiveBounds, InteractiveElement,
+ InteractiveElementState, Interactivity, IntoElement, LayoutId, Model, ModelContext,
+ ModifiersChangedEvent, MouseButton, MouseMoveEvent, Pixels, PlatformInputHandler, Point,
+ ShapedLine, StatefulInteractiveElement, StyleRefinement, Styled, TextRun, TextStyle,
+ TextSystem, UnderlineStyle, WhiteSpace, WindowContext,
};
use itertools::Itertools;
use language::CursorShape;
@@ -598,33 +599,48 @@ impl TerminalElement {
) {
let focus = self.focus.clone();
let terminal = self.terminal.clone();
+ let interactive_bounds = InteractiveBounds {
+ bounds: bounds.intersect(&cx.content_mask().bounds),
+ stacking_order: cx.stacking_order().clone(),
+ };
self.interactivity.on_mouse_down(MouseButton::Left, {
let terminal = terminal.clone();
let focus = focus.clone();
move |e, cx| {
cx.focus(&focus);
- //todo!(context menu)
- // v.context_menu.update(cx, |menu, _cx| menu.delay_cancel());
terminal.update(cx, |terminal, cx| {
terminal.mouse_down(&e, origin);
-
cx.notify();
})
}
});
- self.interactivity.on_mouse_move({
- let terminal = terminal.clone();
- let focus = focus.clone();
- move |e, cx| {
- if e.pressed_button.is_some() && focus.is_focused(cx) && !cx.has_active_drag() {
+
+ cx.on_mouse_event({
+ let bounds = bounds.clone();
+ let focus = self.focus.clone();
+ let terminal = self.terminal.clone();
+ move |e: &MouseMoveEvent, phase, cx| {
+ if phase != DispatchPhase::Bubble || !focus.is_focused(cx) {
+ return;
+ }
+
+ if e.pressed_button.is_some() && !cx.has_active_drag() {
terminal.update(cx, |terminal, cx| {
terminal.mouse_drag(e, origin, bounds);
cx.notify();
})
}
+
+ if interactive_bounds.visibly_contains(&e.position, cx) {
+ terminal.update(cx, |terminal, cx| {
+ terminal.mouse_move(&e, origin);
+ cx.notify();
+ })
+ }
}
});
+
self.interactivity.on_mouse_up(
MouseButton::Left,
TerminalElement::generic_button_handler(
@@ -651,19 +667,6 @@ impl TerminalElement {
}
}
});
-
- self.interactivity.on_mouse_move({
- let terminal = terminal.clone();
- let focus = focus.clone();
- move |e, cx| {
- if focus.is_focused(cx) {
- terminal.update(cx, |terminal, cx| {
- terminal.mouse_move(&e, origin);
- cx.notify();
- })
- }
- }
- });
self.interactivity.on_scroll_wheel({
let terminal = terminal.clone();
move |e, cx| {
@@ -3,11 +3,12 @@ use std::{path::PathBuf, sync::Arc};
use crate::TerminalView;
use db::kvp::KEY_VALUE_STORE;
use gpui::{
- actions, div, serde_json, AppContext, AsyncWindowContext, Entity, EventEmitter, ExternalPaths,
+ actions, serde_json, AppContext, AsyncWindowContext, Entity, EventEmitter, ExternalPaths,
FocusHandle, FocusableView, IntoElement, ParentElement, Pixels, Render, Styled, Subscription,
Task, View, ViewContext, VisualContext, WeakView, WindowContext,
};
use project::Fs;
+use search::{buffer_search::DivRegistrar, BufferSearchBar};
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsStore};
use terminal::terminal_settings::{TerminalDockPosition, TerminalSettings};
@@ -101,9 +102,9 @@ impl TerminalPanel {
})
.into_any_element()
});
- // let buffer_search_bar = cx.build_view(search::BufferSearchBar::new);
- // pane.toolbar()
- // .update(cx, |toolbar, cx| toolbar.add_item(buffer_search_bar, cx));
+ let buffer_search_bar = cx.new_view(search::BufferSearchBar::new);
+ pane.toolbar()
+ .update(cx, |toolbar, cx| toolbar.add_item(buffer_search_bar, cx));
pane
});
let subscriptions = vec![
@@ -329,8 +330,20 @@ impl TerminalPanel {
impl EventEmitter<PanelEvent> for TerminalPanel {}
impl Render for TerminalPanel {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
- div().size_full().child(self.pane.clone())
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+ let mut registrar = DivRegistrar::new(
+ |panel, cx| {
+ panel
+ .pane
+ .read(cx)
+ .toolbar()
+ .read(cx)
+ .item_of_type::<BufferSearchBar>()
+ },
+ cx,
+ );
+ BufferSearchBar::register_inner(&mut registrar);
+ registrar.into_div().size_full().child(self.pane.clone())
}
}
@@ -410,11 +423,6 @@ impl Panel for TerminalPanel {
"TerminalPanel"
}
- // todo!()
- // fn icon_tooltip(&self) -> (String, Option<Box<dyn Action>>) {
- // ("Terminal Panel".into(), Some(Box::new(ToggleFocus)))
- // }
-
fn icon(&self, _cx: &WindowContext) -> Option<Icon> {
Some(Icon::Terminal)
}
@@ -28,7 +28,7 @@ use workspace::{
item::{BreadcrumbText, Item, ItemEvent},
notifications::NotifyResultExt,
register_deserializable_item,
- searchable::{SearchEvent, SearchOptions, SearchableItem},
+ searchable::{SearchEvent, SearchOptions, SearchableItem, SearchableItemHandle},
CloseActiveItem, NewCenterTerminal, Pane, ToolbarItemLocation, Workspace, WorkspaceId,
};
@@ -714,10 +714,9 @@ impl Item for TerminalView {
false
}
- // todo!(search)
- // fn as_searchable(&self, handle: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
- // Some(Box::new(handle.clone()))
- // }
+ fn as_searchable(&self, handle: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
+ Some(Box::new(handle.clone()))
+ }
fn breadcrumb_location(&self) -> ToolbarItemLocation {
ToolbarItemLocation::PrimaryLeft
@@ -150,14 +150,6 @@ pub fn app_menus() -> Vec<Menu<'static>> {
MenuItem::action("View Dependency Licenses", crate::OpenLicenses),
MenuItem::action("Show Welcome", workspace::Welcome),
MenuItem::separator(),
- // todo!(): Needs `feedback` crate.
- // MenuItem::action("Give us feedback", feedback::feedback_editor::GiveFeedback),
- // MenuItem::action(
- // "Copy System Specs Into Clipboard",
- // feedback::CopySystemSpecsIntoClipboard,
- // ),
- // MenuItem::action("File Bug Report", feedback::FileBugReport),
- // MenuItem::action("Request Feature", feedback::RequestFeature),
MenuItem::separator(),
MenuItem::action(
"Documentation",
@@ -400,7 +400,6 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
});
workspace.focus_handle(cx).focus(cx);
- load_default_keymap(cx);
})
.detach();
}
@@ -571,6 +570,8 @@ pub fn handle_keymap_file_changes(
})
.detach();
+ load_default_keymap(cx);
+
cx.spawn(move |cx| async move {
let mut user_keymap = KeymapFile::default();
loop {