mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-16 15:11:25 +00:00
WIP, search bar looks kinda okay
This commit is contained in:
parent
0c23e6738b
commit
b04838c23a
4 changed files with 156 additions and 38 deletions
|
@ -165,7 +165,7 @@ impl Render for BufferSearchBar {
|
|||
let replace_all = should_show_replace_input
|
||||
.then(|| super::render_replace_button(ReplaceAll, ui::Icon::ReplaceAll));
|
||||
let replace_next = should_show_replace_input
|
||||
.then(|| super::render_replace_button(ReplaceNext, ui::Icon::Replace));
|
||||
.then(|| super::render_replace_button(ReplaceNext, ui::Icon::ReplaceNext));
|
||||
let in_replace = self.replacement_editor.focus_handle(cx).is_focused(cx);
|
||||
|
||||
h_stack()
|
||||
|
|
|
@ -13,9 +13,10 @@ use editor::{
|
|||
MultiBuffer, SelectAll, MAX_TAB_TITLE_LEN,
|
||||
};
|
||||
use gpui::{
|
||||
actions, div, Action, AnyElement, AnyView, AppContext, Context as _, Div, Element, Entity,
|
||||
EntityId, EventEmitter, FocusableView, Model, ModelContext, PromptLevel, Render, SharedString,
|
||||
Subscription, Task, View, ViewContext, VisualContext, WeakModel, WeakView, WindowContext,
|
||||
actions, div, white, Action, AnyElement, AnyView, AppContext, Context as _, Div, Element,
|
||||
Entity, EntityId, EventEmitter, FocusableView, InteractiveElement, IntoElement, Model,
|
||||
ModelContext, ParentElement, PromptLevel, Render, SharedString, Styled, Subscription, Task,
|
||||
View, ViewContext, VisualContext, WeakModel, WeakView, WindowContext,
|
||||
};
|
||||
use menu::Confirm;
|
||||
use project::{
|
||||
|
@ -35,6 +36,11 @@ use std::{
|
|||
sync::Arc,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use theme::ActiveTheme;
|
||||
use ui::{
|
||||
h_stack, v_stack, Button, Clickable, Color, Disableable, Icon, IconButton, IconElement, Label,
|
||||
Selectable,
|
||||
};
|
||||
use util::{paths::PathMatcher, ResultExt as _};
|
||||
use workspace::{
|
||||
item::{BreadcrumbText, Item, ItemEvent, ItemHandle},
|
||||
|
@ -318,7 +324,7 @@ impl EventEmitter<ViewEvent> for ProjectSearchView {}
|
|||
impl Render for ProjectSearchView {
|
||||
type Element = Div;
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||
div()
|
||||
div().child(Label::new("xd"))
|
||||
}
|
||||
}
|
||||
// impl Entity for ProjectSearchView {
|
||||
|
@ -569,36 +575,23 @@ impl Item for ProjectSearchView {
|
|||
}
|
||||
|
||||
fn tab_content(&self, _: Option<usize>, cx: &WindowContext<'_>) -> AnyElement {
|
||||
// Flex::row()
|
||||
// .with_child(
|
||||
// Svg::new("icons/magnifying_glass.svg")
|
||||
// .with_color(tab_theme.label.text.color)
|
||||
// .constrained()
|
||||
// .with_width(tab_theme.type_icon_width)
|
||||
// .aligned()
|
||||
// .contained()
|
||||
// .with_margin_right(tab_theme.spacing),
|
||||
// )
|
||||
// .with_child({
|
||||
// let tab_name: Option<Cow<_>> = self
|
||||
// .model
|
||||
// .read(cx)
|
||||
// .search_history
|
||||
// .current()
|
||||
// .as_ref()
|
||||
// .map(|query| {
|
||||
// let query_text = util::truncate_and_trailoff(query, MAX_TAB_TITLE_LEN);
|
||||
// query_text.into()
|
||||
// });
|
||||
// Label::new(
|
||||
// tab_name
|
||||
// .filter(|name| !name.is_empty())
|
||||
// .unwrap_or("Project search".into()),
|
||||
// tab_theme.label.clone(),
|
||||
// )
|
||||
// .aligned()
|
||||
// })
|
||||
div().into_any()
|
||||
let last_query: Option<SharedString> = self
|
||||
.model
|
||||
.read(cx)
|
||||
.search_history
|
||||
.current()
|
||||
.as_ref()
|
||||
.map(|query| {
|
||||
let query_text = util::truncate_and_trailoff(query, MAX_TAB_TITLE_LEN);
|
||||
query_text.into()
|
||||
});
|
||||
let tab_name = last_query
|
||||
.filter(|query| !query.is_empty())
|
||||
.unwrap_or_else(|| "Project search".into());
|
||||
h_stack()
|
||||
.child(IconElement::new(Icon::MagnifyingGlass))
|
||||
.child(Label::new(tab_name))
|
||||
.into_any()
|
||||
}
|
||||
|
||||
fn for_each_project_item(
|
||||
|
@ -1686,7 +1679,127 @@ impl Render for ProjectSearchBar {
|
|||
type Element = Div;
|
||||
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||
div()
|
||||
let Some(search) = self.active_project_search.clone() else {
|
||||
return div();
|
||||
};
|
||||
let search = search.read(cx);
|
||||
let query_column = v_stack()
|
||||
.flex_1()
|
||||
.child(
|
||||
h_stack()
|
||||
.min_w_80()
|
||||
.on_action(cx.listener(|this, _: &ToggleFilters, cx| {
|
||||
this.toggle_filters(cx);
|
||||
}))
|
||||
.on_action(cx.listener(|this, _: &ToggleWholeWord, cx| {
|
||||
this.toggle_search_option(SearchOptions::WHOLE_WORD, cx);
|
||||
}))
|
||||
.on_action(cx.listener(|this, _: &ToggleCaseSensitive, cx| {
|
||||
this.toggle_search_option(SearchOptions::CASE_SENSITIVE, cx);
|
||||
}))
|
||||
.on_action(cx.listener(|this, action: &ToggleReplace, cx| {
|
||||
this.toggle_replace(action, cx);
|
||||
}))
|
||||
.on_action(cx.listener(|this, action: &ActivateTextMode, cx| {
|
||||
this.activate_search_mode(SearchMode::Text, cx)
|
||||
}))
|
||||
.on_action(cx.listener(|this, action: &ActivateRegexMode, cx| {
|
||||
this.activate_search_mode(SearchMode::Regex, cx)
|
||||
}))
|
||||
.child(IconElement::new(Icon::MagnifyingGlass))
|
||||
.child(search.query_editor.clone())
|
||||
.child(
|
||||
h_stack()
|
||||
.child(
|
||||
IconButton::new("project-search-filter-button", Icon::Filter)
|
||||
.on_click(|_, cx| {
|
||||
cx.dispatch_action(ToggleFilters.boxed_clone())
|
||||
}),
|
||||
)
|
||||
.child(IconButton::new(
|
||||
"project-search-case-sensitive",
|
||||
Icon::CaseSensitive,
|
||||
))
|
||||
.child(IconButton::new(
|
||||
"project-search-whole-word",
|
||||
Icon::WholeWord,
|
||||
)),
|
||||
)
|
||||
.border_2()
|
||||
.bg(white())
|
||||
.rounded_lg(),
|
||||
)
|
||||
.when(search.filters_enabled, |this| {
|
||||
this.child(
|
||||
h_stack()
|
||||
.child(search.included_files_editor.clone())
|
||||
.child(search.excluded_files_editor.clone()),
|
||||
)
|
||||
});
|
||||
let mode_column = h_stack()
|
||||
.child(
|
||||
h_stack()
|
||||
.child(
|
||||
Button::new("project-search-text-button", "Text")
|
||||
.selected(search.current_mode == SearchMode::Text)
|
||||
.on_click(|_, cx| cx.dispatch_action(ActivateTextMode.boxed_clone())),
|
||||
)
|
||||
.child(
|
||||
Button::new("project-search-regex-button", "Regex")
|
||||
.selected(search.current_mode == SearchMode::Regex)
|
||||
.on_click(|_, cx| cx.dispatch_action(ActivateRegexMode.boxed_clone())),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
IconButton::new("project-search-toggle-replace", Icon::Replace).on_click(
|
||||
|_, cx| {
|
||||
cx.dispatch_action(ToggleReplace.boxed_clone());
|
||||
},
|
||||
),
|
||||
);
|
||||
let replace_column = if search.replace_enabled {
|
||||
h_stack()
|
||||
.bg(white())
|
||||
.flex_1()
|
||||
.border_2()
|
||||
.rounded_lg()
|
||||
.child(IconElement::new(Icon::Replace).size(ui::IconSize::Small))
|
||||
.child(search.replacement_editor.clone())
|
||||
} else {
|
||||
// Fill out the space if we don't have a replacement editor.
|
||||
h_stack().size_full()
|
||||
};
|
||||
let actions_column = h_stack()
|
||||
.when(search.replace_enabled, |this| {
|
||||
this.children([
|
||||
IconButton::new("project-search-replace-next", Icon::ReplaceNext),
|
||||
IconButton::new("project-search-replace-all", Icon::ReplaceAll),
|
||||
])
|
||||
})
|
||||
.when_some(search.active_match_index, |this, index| {
|
||||
let match_quantity = search.model.read(cx).match_ranges.len();
|
||||
debug_assert!(match_quantity > index);
|
||||
this.child(IconButton::new(
|
||||
"project-search-select-all",
|
||||
Icon::SelectAll,
|
||||
))
|
||||
.child(Label::new(format!("{index}/{match_quantity}")))
|
||||
})
|
||||
.children([
|
||||
IconButton::new("project-search-prev-match", Icon::ChevronLeft)
|
||||
.disabled(search.active_match_index.is_none()),
|
||||
IconButton::new("project-search-next-match", Icon::ChevronRight)
|
||||
.disabled(search.active_match_index.is_none()),
|
||||
]);
|
||||
h_stack()
|
||||
.size_full()
|
||||
.p_1()
|
||||
.m_2()
|
||||
.justify_between()
|
||||
.child(query_column)
|
||||
.child(mode_column)
|
||||
.child(replace_column)
|
||||
.child(actions_column)
|
||||
}
|
||||
}
|
||||
// impl Entity for ProjectSearchBar {
|
||||
|
|
|
@ -61,6 +61,7 @@ pub enum Icon {
|
|||
FileRust,
|
||||
FileToml,
|
||||
FileTree,
|
||||
Filter,
|
||||
Folder,
|
||||
FolderOpen,
|
||||
FolderX,
|
||||
|
@ -80,6 +81,7 @@ pub enum Icon {
|
|||
Quote,
|
||||
Replace,
|
||||
ReplaceAll,
|
||||
ReplaceNext,
|
||||
Screen,
|
||||
SelectAll,
|
||||
Split,
|
||||
|
@ -138,6 +140,7 @@ impl Icon {
|
|||
Icon::FileRust => "icons/file_icons/rust.svg",
|
||||
Icon::FileToml => "icons/file_icons/toml.svg",
|
||||
Icon::FileTree => "icons/project.svg",
|
||||
Icon::Filter => "icons/filter.svg",
|
||||
Icon::Folder => "icons/file_icons/folder.svg",
|
||||
Icon::FolderOpen => "icons/file_icons/folder_open.svg",
|
||||
Icon::FolderX => "icons/stop_sharing.svg",
|
||||
|
@ -157,6 +160,7 @@ impl Icon {
|
|||
Icon::Quote => "icons/quote.svg",
|
||||
Icon::Replace => "icons/replace.svg",
|
||||
Icon::ReplaceAll => "icons/replace_all.svg",
|
||||
Icon::ReplaceNext => "icons/replace_next.svg",
|
||||
Icon::Screen => "icons/desktop.svg",
|
||||
Icon::SelectAll => "icons/select-all.svg",
|
||||
Icon::Split => "icons/split.svg",
|
||||
|
|
|
@ -24,6 +24,7 @@ use anyhow::{anyhow, Context as _};
|
|||
use futures::{channel::mpsc, StreamExt};
|
||||
use project_panel::ProjectPanel;
|
||||
use quick_action_bar::QuickActionBar;
|
||||
use search::project_search::ProjectSearchBar;
|
||||
use settings::{initial_local_settings_content, load_default_keymap, KeymapFile, Settings};
|
||||
use std::{borrow::Cow, ops::Deref, sync::Arc};
|
||||
use terminal_view::terminal_panel::TerminalPanel;
|
||||
|
@ -426,8 +427,8 @@ fn initialize_pane(workspace: &mut Workspace, pane: &View<Pane>, cx: &mut ViewCo
|
|||
toolbar.add_item(quick_action_bar, cx);
|
||||
let diagnostic_editor_controls = cx.build_view(|_| diagnostics::ToolbarControls::new());
|
||||
// toolbar.add_item(diagnostic_editor_controls, cx);
|
||||
// let project_search_bar = cx.add_view(|_| ProjectSearchBar::new());
|
||||
// toolbar.add_item(project_search_bar, cx);
|
||||
let project_search_bar = cx.build_view(|_| ProjectSearchBar::new());
|
||||
toolbar.add_item(project_search_bar, cx);
|
||||
// let lsp_log_item =
|
||||
// cx.add_view(|_| language_tools::LspLogToolbarItemView::new());
|
||||
// toolbar.add_item(lsp_log_item, cx);
|
||||
|
|
Loading…
Reference in a new issue