use std::ops::Range;use std::path::PathBuf;use std::sync::Arc; use gpui::{AnyElement, App, Entity, IntoElement, Window};use language::{Anchor, Buffer, HighlightedText};use project::Symbol; /// The editor-agnostic interface a [`Picker`](crate::Picker) uses to drive its/// preview.pub trait PreviewBackend: 'static { fn update(&self, update: Update, window: &mut Window, cx: &mut App); fn render(&self, layout: Layout, cx: &mut App) -> AnyElement; /// Called after a resize to let the preview do resizing logic like scrolling. fn adjust_to_new_size(&self, window: &mut Window, cx: &mut App); /// Empty the preview and show a placeholder message. fn clear(&self, cx: &mut App);} /// The preview window of a [`Picker`](crate::Picker).pub struct Preview { content: Arc<dyn PreviewBackend>, pub(crate) layout: Layout,} #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]pub enum Layout { #[default] Hidden, Below, Right,} impl Preview { pub fn new(content: Arc<dyn PreviewBackend>) -> Self { Preview { content, layout: Layout::default(), } } pub fn update(&mut self, update: Update, window: &mut Window, cx: &mut App) { self.content.update(update, window, cx); } pub fn render(&self, cx: &mut App) -> impl IntoElement { self.content.render(self.layout, cx) } pub fn adjust_to_new_size(&self, window: &mut Window, cx: &mut App) { self.content.adjust_to_new_size(window, cx); } pub(crate) fn clear(&self, cx: &mut App) { self.content.clear(cx); }} /// Identifies what a preview should show.pub enum PreviewSource { /// The buffer is identified by its absolute path; the preview opens it. /// /// Used by pickers (like the file finder) that only know the path of the /// match. Path(PathBuf), /// The buffer is provided directly. /// /// Used by pickers (like the text picker) that already hold the matched /// buffer. Buffer(Entity<Buffer>), /// The buffer is identified by a project symbol; the preview opens it and /// highlights the symbol's range. /// /// Used by pickers (like the project symbols picker) that only know the /// matched symbol. The highlight is derived from the symbol once its buffer /// loads, so callers don't supply a [`MatchLocation`]. Symbol(Symbol), /// No buffer to show; display this message centered in the preview instead. /// /// Used by pickers that have a selection without a previewable buffer (like /// the file finder's "create new file" entry). Built as a [`HighlightedText`] /// so callers can emphasize parts of the message (e.g. a file path). Message(HighlightedText),} pub struct MatchLocation { /// The location of the match (for highlighting) pub anchor_range: Range<Anchor>, /// The location of the match as an offset (for scrolling) pub range: Range<usize>,} /// An update for the [`Preview`] window of a [`Picker`](crate::Picker).pub struct Update { /// Where to source the buffer to preview. pub source: PreviewSource, /// The location to highlight and scroll to, if any. pub match_location: Option<MatchLocation>,} impl Update { /// Preview the buffer at `abs_path` without highlighting anything. pub fn from_path(abs_path: PathBuf) -> Self { Self { source: PreviewSource::Path(abs_path), match_location: None, } } /// Show `message` centered in the preview instead of a buffer. /// /// The message is a [`HighlightedText`], so parts of it (e.g. a file path) /// can be emphasized. pub fn message(message: HighlightedText) -> Self { Self { source: PreviewSource::Message(message), match_location: None, } } /// Preview `buffer`, highlighting and scrolling to `highlight`. pub fn from_buffer(buffer: Entity<Buffer>, highlight: MatchLocation) -> Self { Self { source: PreviewSource::Buffer(buffer), match_location: Some(highlight), } } /// Preview the buffer for `symbol`, highlighting and scrolling to its range. /// /// The buffer is opened and the highlight derived by the preview once the /// buffer loads. pub fn from_symbol(symbol: Symbol) -> Self { Self { source: PreviewSource::Symbol(symbol), match_location: None, } }}
use std::ops::Range;
use std::path::PathBuf;
use std::sync::Arc;
use gpui::{AnyElement, App, Entity, IntoElement, Window};
use language::{Anchor, Buffer, HighlightedText};
use project::Symbol;
/// The editor-agnostic interface a [`Picker`](crate::Picker) uses to drive its
/// preview.
pub trait PreviewBackend: 'static {
fn update(&self, update: Update, window: &mut Window, cx: &mut App);
fn render(&self, layout: Layout, cx: &mut App) -> AnyElement;
/// Called after a resize to let the preview do resizing logic like scrolling.
fn adjust_to_new_size(&self, window: &mut Window, cx: &mut App);
/// Empty the preview and show a placeholder message.
fn clear(&self, cx: &mut App);
}
/// The preview window of a [`Picker`](crate::Picker).
pub struct Preview {
content: Arc<dyn PreviewBackend>,
pub(crate) layout: Layout,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Layout {
#[default]
Hidden,
Below,
Right,
}
impl Preview {
pub fn new(content: Arc<dyn PreviewBackend>) -> Self {
Preview {
content,
layout: Layout::default(),
}
}
pub fn update(&mut self, update: Update, window: &mut Window, cx: &mut App) {
self.content.update(update, window, cx);
}
pub fn render(&self, cx: &mut App) -> impl IntoElement {
self.content.render(self.layout, cx)
}
pub fn adjust_to_new_size(&self, window: &mut Window, cx: &mut App) {
self.content.adjust_to_new_size(window, cx);
}
pub(crate) fn clear(&self, cx: &mut App) {
self.content.clear(cx);
}
}
/// Identifies what a preview should show.
pub enum PreviewSource {
/// The buffer is identified by its absolute path; the preview opens it.
///
/// Used by pickers (like the file finder) that only know the path of the
/// match.
Path(PathBuf),
/// The buffer is provided directly.
///
/// Used by pickers (like the text picker) that already hold the matched
/// buffer.
Buffer(Entity<Buffer>),
/// The buffer is identified by a project symbol; the preview opens it and
/// highlights the symbol's range.
///
/// Used by pickers (like the project symbols picker) that only know the
/// matched symbol. The highlight is derived from the symbol once its buffer
/// loads, so callers don't supply a [`MatchLocation`].
Symbol(Symbol),
/// No buffer to show; display this message centered in the preview instead.
///
/// Used by pickers that have a selection without a previewable buffer (like
/// the file finder's "create new file" entry). Built as a [`HighlightedText`]
/// so callers can emphasize parts of the message (e.g. a file path).
Message(HighlightedText),
}
pub struct MatchLocation {
/// The location of the match (for highlighting)
pub anchor_range: Range<Anchor>,
/// The location of the match as an offset (for scrolling)
pub range: Range<usize>,
}
/// An update for the [`Preview`] window of a [`Picker`](crate::Picker).
pub struct Update {
/// Where to source the buffer to preview.
pub source: PreviewSource,
/// The location to highlight and scroll to, if any.
pub match_location: Option<MatchLocation>,
}
impl Update {
/// Preview the buffer at `abs_path` without highlighting anything.
pub fn from_path(abs_path: PathBuf) -> Self {
Self {
source: PreviewSource::Path(abs_path),
match_location: None,
}
}
/// Show `message` centered in the preview instead of a buffer.
///
/// The message is a [`HighlightedText`], so parts of it (e.g. a file path)
/// can be emphasized.
pub fn message(message: HighlightedText) -> Self {
Self {
source: PreviewSource::Message(message),
match_location: None,
}
}
/// Preview `buffer`, highlighting and scrolling to `highlight`.
pub fn from_buffer(buffer: Entity<Buffer>, highlight: MatchLocation) -> Self {
Self {
source: PreviewSource::Buffer(buffer),
match_location: Some(highlight),
}
}
/// Preview the buffer for `symbol`, highlighting and scrolling to its range.
///
/// The buffer is opened and the highlight derived by the preview once the
/// buffer loads.
pub fn from_symbol(symbol: Symbol) -> Self {
Self {
source: PreviewSource::Symbol(symbol),
match_location: None,
}
}
}