Snapshot for kirill

This commit is contained in:
Mikayla 2023-11-06 12:33:20 -08:00
parent 050d72719a
commit 3f7dc59512
No known key found for this signature in database
7 changed files with 540 additions and 0 deletions

17
Cargo.lock generated
View File

@ -6006,6 +6006,23 @@ dependencies = [
"workspace", "workspace",
] ]
[[package]]
name = "picker2"
version = "0.1.0"
dependencies = [
"ctor",
"editor2",
"env_logger 0.9.3",
"gpui2",
"menu2",
"parking_lot 0.11.2",
"serde_json",
"settings2",
"theme2",
"util",
"workspace2",
]
[[package]] [[package]]
name = "pico-args" name = "pico-args"
version = "0.4.2" version = "0.4.2"

View File

@ -67,6 +67,7 @@ members = [
"crates/notifications", "crates/notifications",
"crates/outline", "crates/outline",
"crates/picker", "crates/picker",
"crates/picker2",
"crates/plugin", "crates/plugin",
"crates/plugin_macros", "crates/plugin_macros",
"crates/plugin_runtime", "crates/plugin_runtime",

View File

@ -1,5 +1,6 @@
mod div; mod div;
mod img; mod img;
mod list;
mod svg; mod svg;
mod text; mod text;

View File

@ -1,3 +1,5 @@
use std::sync::Arc;
use crate::{ use crate::{
div, AnyElement, BorrowWindow, Bounds, Component, Div, DivState, Element, ElementFocus, div, AnyElement, BorrowWindow, Bounds, Component, Div, DivState, Element, ElementFocus,
ElementId, ElementInteraction, FocusDisabled, FocusEnabled, FocusListeners, Focusable, ElementId, ElementInteraction, FocusDisabled, FocusEnabled, FocusListeners, Focusable,

View File

@ -0,0 +1,91 @@
use std::ops::Range;
use smallvec::SmallVec;
use crate::{AnyElement, Component, Element, ElementId, StyleRefinement, ViewContext};
// We want to support uniform and non-uniform height
// We need to make the ID mandatory, to replace the 'state' field
// Previous implementation measured the first element as early as possible
fn list<'a, Id, V, Iter, C>(
id: Id,
f: impl 'static + FnOnce(&'a mut V, Range<usize>, &'a mut ViewContext<V>) -> Iter,
) -> List<V>
where
Id: Into<ElementId>,
V: 'static,
Iter: 'a + Iterator<Item = C>,
C: Component<V>,
{
List {
id: id.into(),
render_items: Box::new(|view, visible_range, cx| {
f(view, visible_range, cx)
.map(|element| element.render())
.collect()
}),
}
}
struct List<V> {
id: ElementId,
render_items: Box<
dyn for<'a> FnOnce(
&'a mut V,
Range<usize>,
&'a mut ViewContext<V>,
) -> SmallVec<[AnyElement<V>; 64]>,
>,
}
impl<V> List<V> {}
// #[derive(Debug)]
// pub enum ScrollTarget {
// Show(usize),
// Center(usize),
// }
#[derive(Default)]
struct ListState {
scroll_top: f32,
style: StyleRefinement,
// todo
// scroll_to: Option<ScrollTarget>,
}
impl<V: 'static> Element<V> for List<V> {
type ElementState = ListState;
fn id(&self) -> Option<crate::ElementId> {
Some(self.id)
}
fn initialize(
&mut self,
_: &mut V,
element_state: Option<Self::ElementState>,
_: &mut crate::ViewContext<V>,
) -> Self::ElementState {
let element_state = element_state.unwrap_or_default();
element_state
}
fn layout(
&mut self,
view_state: &mut V,
element_state: &mut Self::ElementState,
cx: &mut crate::ViewContext<V>,
) -> crate::LayoutId {
todo!()
}
fn paint(
&mut self,
bounds: crate::Bounds<crate::Pixels>,
view_state: &mut V,
element_state: &mut Self::ElementState,
cx: &mut crate::ViewContext<V>,
) {
}
}

28
crates/picker2/Cargo.toml Normal file
View File

@ -0,0 +1,28 @@
[package]
name = "picker2"
version = "0.1.0"
edition = "2021"
publish = false
[lib]
path = "src/picker2.rs"
doctest = false
[dependencies]
editor = { package = "editor2", path = "../editor2" }
gpui = { package = "gpui2", path = "../gpui2" }
menu = { package = "menu2", path = "../menu2" }
settings = { package = "settings2", path = "../settings2" }
util = { path = "../util" }
theme = { package = "theme2", path = "../theme2" }
workspace = { package = "workspace2", path = "../workspace2" }
parking_lot.workspace = true
[dev-dependencies]
editor = { package = "editor2", path = "../editor2", features = ["test-support"] }
gpui = { package = "gpui2", path = "../gpui2", features = ["test-support"] }
serde_json.workspace = true
workspace = { package = "workspace2", path = "../workspace2", features = ["test-support"] }
ctor.workspace = true
env_logger.workspace = true

View File

@ -0,0 +1,400 @@
// use editor::Editor;
// use gpui::{
// elements::*,
// geometry::vector::{vec2f, Vector2F},
// keymap_matcher::KeymapContext,
// platform::{CursorStyle, MouseButton},
// AnyElement, AnyViewHandle, AppContext, Axis, Entity, MouseState, Task, View, ViewContext,
// ViewHandle,
// };
// use menu::{Cancel, Confirm, SecondaryConfirm, SelectFirst, SelectLast, SelectNext, SelectPrev};
// use parking_lot::Mutex;
// use std::{cmp, sync::Arc};
// use util::ResultExt;
// use workspace::Modal;
// #[derive(Clone, Copy)]
// pub enum PickerEvent {
// Dismiss,
// }
use std::ops::Range;
use gpui::{div, AppContext, Component, Div, Element, ParentElement, Render, ViewContext};
pub struct Picker<D> {
delegate: D,
// query_editor: ViewHandle<Editor>,
// list_state: UniformListState,
// max_size: Vector2F,
// theme: Arc<Mutex<Box<dyn Fn(&theme::Theme) -> theme::Picker>>>,
// confirmed: bool,
// pending_update_matches: Option<Task<Option<()>>>,
// confirm_on_update: Option<bool>,
// has_focus: bool,
}
pub trait PickerDelegate: Sized + 'static {
type ListItem: Element<Picker<Self>>;
// fn placeholder_text(&self) -> Arc<str>;
// fn match_count(&self) -> usize;
// fn selected_index(&self) -> usize;
// fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>);
// fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()>;
// fn confirm(&mut self, secondary: bool, cx: &mut ViewContext<Picker<Self>>);
// fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>);
// todo!("rename to render_candidate?")
fn render_match(
&self,
ix: usize,
active: bool,
hovered: bool,
selected: bool,
cx: &mut ViewContext<Picker<Self>>,
) -> Self::ListItem;
// fn center_selection_after_match_updates(&self) -> bool {
// false
// }
// fn render_header(
// &self,
// _cx: &mut ViewContext<Picker<Self>>,
// ) -> Option<AnyElement<Picker<Self>>> {
// None
// }
// fn render_footer(
// &self,
// _cx: &mut ViewContext<Picker<Self>>,
// ) -> Option<AnyElement<Picker<Self>>> {
// None
// }
}
// impl<D: PickerDelegate> Entity for Picker<D> {
// type Event = PickerEvent;
// }
impl<D: PickerDelegate> Render for Picker<D> {
type Element = Div<Self>;
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
div().child(list(
"candidates",
|this: &mut Picker<D>, visible_range, cx| {
visible_range
.into_iter()
.map(|ix| this.delegate.render_match(ix, false, false, false, cx))
},
))
}
}
fn list<'a, D: PickerDelegate, F, I>(id: &'static str, f: F) -> Div<Picker<D>>
where
F: FnOnce(&'a mut Picker<D>, Range<usize>, &'a mut ViewContext<Picker<D>>) -> I,
I: 'a + Iterator<Item = D::ListItem>,
{
todo!();
}
// impl<D: PickerDelegate> View for Picker<D> {
// fn ui_name() -> &'static str {
// "Picker"
// }
// fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
// let theme = (self.theme.lock())(theme::current(cx).as_ref());
// let query = self.query(cx);
// let match_count = self.delegate.match_count();
// let container_style;
// let editor_style;
// if query.is_empty() && match_count == 0 {
// container_style = theme.empty_container;
// editor_style = theme.empty_input_editor.container;
// } else {
// container_style = theme.container;
// editor_style = theme.input_editor.container;
// };
// Flex::new(Axis::Vertical)
// .with_child(
// ChildView::new(&self.query_editor, cx)
// .contained()
// .with_style(editor_style),
// )
// .with_children(self.delegate.render_header(cx))
// .with_children(if match_count == 0 {
// if query.is_empty() {
// None
// } else {
// Some(
// Label::new("No matches", theme.no_matches.label.clone())
// .contained()
// .with_style(theme.no_matches.container)
// .into_any(),
// )
// }
// } else {
// Some(
// UniformList::new(
// self.list_state.clone(),
// match_count,
// cx,
// move |this, mut range, items, cx| {
// let selected_ix = this.delegate.selected_index();
// range.end = cmp::min(range.end, this.delegate.match_count());
// items.extend(range.map(move |ix| {
// MouseEventHandler::new::<D, _>(ix, cx, |state, cx| {
// this.delegate.render_match(ix, state, ix == selected_ix, cx)
// })
// // Capture mouse events
// .on_down(MouseButton::Left, |_, _, _| {})
// .on_up(MouseButton::Left, |_, _, _| {})
// .on_click(MouseButton::Left, move |click, picker, cx| {
// picker.select_index(ix, click.cmd, cx);
// })
// .with_cursor_style(CursorStyle::PointingHand)
// .into_any()
// }));
// },
// )
// .contained()
// .with_margin_top(6.0)
// .flex(1., false)
// .into_any(),
// )
// })
// .with_children(self.delegate.render_footer(cx))
// .contained()
// .with_style(container_style)
// .constrained()
// .with_max_width(self.max_size.x())
// .with_max_height(self.max_size.y())
// .into_any_named("picker")
// }
// fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
// Self::reset_to_default_keymap_context(keymap);
// keymap.add_identifier("menu");
// }
// fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
// self.has_focus = true;
// if cx.is_self_focused() {
// cx.focus(&self.query_editor);
// }
// }
// fn focus_out(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {
// self.has_focus = false;
// }
// }
// impl<D: PickerDelegate> Modal for Picker<D> {
// fn has_focus(&self) -> bool {
// self.has_focus
// }
// fn dismiss_on_event(event: &Self::Event) -> bool {
// matches!(event, PickerEvent::Dismiss)
// }
// }
// impl<D: PickerDelegate> Picker<D> {
// pub fn init(cx: &mut AppContext) {
// cx.add_action(Self::select_first);
// cx.add_action(Self::select_last);
// cx.add_action(Self::select_next);
// cx.add_action(Self::select_prev);
// cx.add_action(Self::confirm);
// cx.add_action(Self::secondary_confirm);
// cx.add_action(Self::cancel);
// }
// pub fn new(delegate: D, cx: &mut ViewContext<Self>) -> Self {
// let theme = Arc::new(Mutex::new(
// Box::new(|theme: &theme::Theme| theme.picker.clone())
// as Box<dyn Fn(&theme::Theme) -> theme::Picker>,
// ));
// let placeholder_text = delegate.placeholder_text();
// let query_editor = cx.add_view({
// let picker_theme = theme.clone();
// |cx| {
// let mut editor = Editor::single_line(
// Some(Arc::new(move |theme| {
// (picker_theme.lock())(theme).input_editor.clone()
// })),
// cx,
// );
// editor.set_placeholder_text(placeholder_text, cx);
// editor
// }
// });
// cx.subscribe(&query_editor, Self::on_query_editor_event)
// .detach();
// let mut this = Self {
// query_editor,
// list_state: Default::default(),
// delegate,
// max_size: vec2f(540., 420.),
// theme,
// confirmed: false,
// pending_update_matches: None,
// confirm_on_update: None,
// has_focus: false,
// };
// this.update_matches(String::new(), cx);
// this
// }
// pub fn with_max_size(mut self, width: f32, height: f32) -> Self {
// self.max_size = vec2f(width, height);
// self
// }
// pub fn with_theme<F>(self, theme: F) -> Self
// where
// F: 'static + Fn(&theme::Theme) -> theme::Picker,
// {
// *self.theme.lock() = Box::new(theme);
// self
// }
// pub fn delegate(&self) -> &D {
// &self.delegate
// }
// pub fn delegate_mut(&mut self) -> &mut D {
// &mut self.delegate
// }
// pub fn query(&self, cx: &AppContext) -> String {
// self.query_editor.read(cx).text(cx)
// }
// pub fn set_query(&self, query: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
// self.query_editor
// .update(cx, |editor, cx| editor.set_text(query, cx));
// }
// fn on_query_editor_event(
// &mut self,
// _: ViewHandle<Editor>,
// event: &editor::Event,
// cx: &mut ViewContext<Self>,
// ) {
// match event {
// editor::Event::BufferEdited { .. } => self.update_matches(self.query(cx), cx),
// editor::Event::Blurred if !self.confirmed => {
// self.dismiss(cx);
// }
// _ => {}
// }
// }
// pub fn update_matches(&mut self, query: String, cx: &mut ViewContext<Self>) {
// let update = self.delegate.update_matches(query, cx);
// self.matches_updated(cx);
// self.pending_update_matches = Some(cx.spawn(|this, mut cx| async move {
// update.await;
// this.update(&mut cx, |this, cx| {
// this.matches_updated(cx);
// })
// .log_err()
// }));
// }
// fn matches_updated(&mut self, cx: &mut ViewContext<Self>) {
// let index = self.delegate.selected_index();
// let target = if self.delegate.center_selection_after_match_updates() {
// ScrollTarget::Center(index)
// } else {
// ScrollTarget::Show(index)
// };
// self.list_state.scroll_to(target);
// self.pending_update_matches = None;
// if let Some(secondary) = self.confirm_on_update.take() {
// self.confirmed = true;
// self.delegate.confirm(secondary, cx)
// }
// cx.notify();
// }
// pub fn select_first(&mut self, _: &SelectFirst, cx: &mut ViewContext<Self>) {
// if self.delegate.match_count() > 0 {
// self.delegate.set_selected_index(0, cx);
// self.list_state.scroll_to(ScrollTarget::Show(0));
// }
// cx.notify();
// }
// pub fn select_index(&mut self, index: usize, cmd: bool, cx: &mut ViewContext<Self>) {
// if self.delegate.match_count() > 0 {
// self.confirmed = true;
// self.delegate.set_selected_index(index, cx);
// self.delegate.confirm(cmd, cx);
// }
// }
// pub fn select_last(&mut self, _: &SelectLast, cx: &mut ViewContext<Self>) {
// let match_count = self.delegate.match_count();
// if match_count > 0 {
// let index = match_count - 1;
// self.delegate.set_selected_index(index, cx);
// self.list_state.scroll_to(ScrollTarget::Show(index));
// }
// cx.notify();
// }
// pub fn select_next(&mut self, _: &SelectNext, cx: &mut ViewContext<Self>) {
// let next_index = self.delegate.selected_index() + 1;
// if next_index < self.delegate.match_count() {
// self.delegate.set_selected_index(next_index, cx);
// self.list_state.scroll_to(ScrollTarget::Show(next_index));
// }
// cx.notify();
// }
// pub fn select_prev(&mut self, _: &SelectPrev, cx: &mut ViewContext<Self>) {
// let mut selected_index = self.delegate.selected_index();
// if selected_index > 0 {
// selected_index -= 1;
// self.delegate.set_selected_index(selected_index, cx);
// self.list_state
// .scroll_to(ScrollTarget::Show(selected_index));
// }
// cx.notify();
// }
// pub fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
// if self.pending_update_matches.is_some() {
// self.confirm_on_update = Some(false)
// } else {
// self.confirmed = true;
// self.delegate.confirm(false, cx);
// }
// }
// pub fn secondary_confirm(&mut self, _: &SecondaryConfirm, cx: &mut ViewContext<Self>) {
// if self.pending_update_matches.is_some() {
// self.confirm_on_update = Some(true)
// } else {
// self.confirmed = true;
// self.delegate.confirm(true, cx);
// }
// }
// fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
// self.dismiss(cx);
// }
// fn dismiss(&mut self, cx: &mut ViewContext<Self>) {
// cx.emit(PickerEvent::Dismiss);
// self.delegate.dismissed(cx);
// }
// }