mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-19 18:41:56 +03:00
Pass a RenderContext to UniformList
In some cases, we need to render during layout. Previously, we were rendering with a LayoutContext in some cases, but this commit adds the ability to retrieve a render context with a given handle and we use that feature in UniformList. Co-Authored-By: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
parent
d69776585d
commit
2ea085b178
@ -592,11 +592,11 @@ impl ContextMenu {
|
|||||||
&self,
|
&self,
|
||||||
cursor_position: DisplayPoint,
|
cursor_position: DisplayPoint,
|
||||||
style: EditorStyle,
|
style: EditorStyle,
|
||||||
cx: &AppContext,
|
cx: &mut RenderContext<Editor>,
|
||||||
) -> (DisplayPoint, ElementBox) {
|
) -> (DisplayPoint, ElementBox) {
|
||||||
match self {
|
match self {
|
||||||
ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)),
|
ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)),
|
||||||
ContextMenu::CodeActions(menu) => menu.render(cursor_position, style),
|
ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -633,54 +633,62 @@ impl CompletionsMenu {
|
|||||||
!self.matches.is_empty()
|
!self.matches.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&self, style: EditorStyle, _: &AppContext) -> ElementBox {
|
fn render(&self, style: EditorStyle, cx: &mut RenderContext<Editor>) -> ElementBox {
|
||||||
enum CompletionTag {}
|
enum CompletionTag {}
|
||||||
|
|
||||||
let completions = self.completions.clone();
|
let completions = self.completions.clone();
|
||||||
let matches = self.matches.clone();
|
let matches = self.matches.clone();
|
||||||
let selected_item = self.selected_item;
|
let selected_item = self.selected_item;
|
||||||
let container_style = style.autocomplete.container;
|
let container_style = style.autocomplete.container;
|
||||||
UniformList::new(self.list.clone(), matches.len(), move |range, items, cx| {
|
UniformList::new(
|
||||||
let start_ix = range.start;
|
self.list.clone(),
|
||||||
for (ix, mat) in matches[range].iter().enumerate() {
|
matches.len(),
|
||||||
let completion = &completions[mat.candidate_id];
|
cx,
|
||||||
let item_ix = start_ix + ix;
|
move |_, range, items, cx| {
|
||||||
items.push(
|
let start_ix = range.start;
|
||||||
MouseEventHandler::new::<CompletionTag, _, _>(
|
for (ix, mat) in matches[range].iter().enumerate() {
|
||||||
mat.candidate_id,
|
let completion = &completions[mat.candidate_id];
|
||||||
cx,
|
let item_ix = start_ix + ix;
|
||||||
|state, _| {
|
items.push(
|
||||||
let item_style = if item_ix == selected_item {
|
MouseEventHandler::new::<CompletionTag, _, _>(
|
||||||
style.autocomplete.selected_item
|
mat.candidate_id,
|
||||||
} else if state.hovered {
|
cx,
|
||||||
style.autocomplete.hovered_item
|
|state, _| {
|
||||||
} else {
|
let item_style = if item_ix == selected_item {
|
||||||
style.autocomplete.item
|
style.autocomplete.selected_item
|
||||||
};
|
} else if state.hovered {
|
||||||
|
style.autocomplete.hovered_item
|
||||||
|
} else {
|
||||||
|
style.autocomplete.item
|
||||||
|
};
|
||||||
|
|
||||||
Text::new(completion.label.text.clone(), style.text.clone())
|
Text::new(completion.label.text.clone(), style.text.clone())
|
||||||
.with_soft_wrap(false)
|
.with_soft_wrap(false)
|
||||||
.with_highlights(combine_syntax_and_fuzzy_match_highlights(
|
.with_highlights(combine_syntax_and_fuzzy_match_highlights(
|
||||||
&completion.label.text,
|
&completion.label.text,
|
||||||
style.text.color.into(),
|
style.text.color.into(),
|
||||||
styled_runs_for_code_label(&completion.label, &style.syntax),
|
styled_runs_for_code_label(
|
||||||
&mat.positions,
|
&completion.label,
|
||||||
))
|
&style.syntax,
|
||||||
.contained()
|
),
|
||||||
.with_style(item_style)
|
&mat.positions,
|
||||||
.boxed()
|
))
|
||||||
},
|
.contained()
|
||||||
)
|
.with_style(item_style)
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.boxed()
|
||||||
.on_mouse_down(move |cx| {
|
},
|
||||||
cx.dispatch_action(ConfirmCompletion {
|
)
|
||||||
item_ix: Some(item_ix),
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
});
|
.on_mouse_down(move |cx| {
|
||||||
})
|
cx.dispatch_action(ConfirmCompletion {
|
||||||
.boxed(),
|
item_ix: Some(item_ix),
|
||||||
);
|
});
|
||||||
}
|
})
|
||||||
})
|
.boxed(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
.with_width_from_item(
|
.with_width_from_item(
|
||||||
self.matches
|
self.matches
|
||||||
.iter()
|
.iter()
|
||||||
@ -772,14 +780,18 @@ impl CodeActionsMenu {
|
|||||||
&self,
|
&self,
|
||||||
mut cursor_position: DisplayPoint,
|
mut cursor_position: DisplayPoint,
|
||||||
style: EditorStyle,
|
style: EditorStyle,
|
||||||
|
cx: &mut RenderContext<Editor>,
|
||||||
) -> (DisplayPoint, ElementBox) {
|
) -> (DisplayPoint, ElementBox) {
|
||||||
enum ActionTag {}
|
enum ActionTag {}
|
||||||
|
|
||||||
let container_style = style.autocomplete.container;
|
let container_style = style.autocomplete.container;
|
||||||
let actions = self.actions.clone();
|
let actions = self.actions.clone();
|
||||||
let selected_item = self.selected_item;
|
let selected_item = self.selected_item;
|
||||||
let element =
|
let element = UniformList::new(
|
||||||
UniformList::new(self.list.clone(), actions.len(), move |range, items, cx| {
|
self.list.clone(),
|
||||||
|
actions.len(),
|
||||||
|
cx,
|
||||||
|
move |_, range, items, cx| {
|
||||||
let start_ix = range.start;
|
let start_ix = range.start;
|
||||||
for (ix, action) in actions[range].iter().enumerate() {
|
for (ix, action) in actions[range].iter().enumerate() {
|
||||||
let item_ix = start_ix + ix;
|
let item_ix = start_ix + ix;
|
||||||
@ -808,17 +820,18 @@ impl CodeActionsMenu {
|
|||||||
.boxed(),
|
.boxed(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
.with_width_from_item(
|
)
|
||||||
self.actions
|
.with_width_from_item(
|
||||||
.iter()
|
self.actions
|
||||||
.enumerate()
|
.iter()
|
||||||
.max_by_key(|(_, action)| action.lsp_action.title.chars().count())
|
.enumerate()
|
||||||
.map(|(ix, _)| ix),
|
.max_by_key(|(_, action)| action.lsp_action.title.chars().count())
|
||||||
)
|
.map(|(ix, _)| ix),
|
||||||
.contained()
|
)
|
||||||
.with_style(container_style)
|
.contained()
|
||||||
.boxed();
|
.with_style(container_style)
|
||||||
|
.boxed();
|
||||||
|
|
||||||
if self.deployed_from_indicator {
|
if self.deployed_from_indicator {
|
||||||
*cursor_position.column_mut() = 0;
|
*cursor_position.column_mut() = 0;
|
||||||
@ -2578,7 +2591,7 @@ impl Editor {
|
|||||||
pub fn render_code_actions_indicator(
|
pub fn render_code_actions_indicator(
|
||||||
&self,
|
&self,
|
||||||
style: &EditorStyle,
|
style: &EditorStyle,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut RenderContext<Self>,
|
||||||
) -> Option<ElementBox> {
|
) -> Option<ElementBox> {
|
||||||
if self.available_code_actions.is_some() {
|
if self.available_code_actions.is_some() {
|
||||||
enum Tag {}
|
enum Tag {}
|
||||||
@ -2612,7 +2625,7 @@ impl Editor {
|
|||||||
&self,
|
&self,
|
||||||
cursor_position: DisplayPoint,
|
cursor_position: DisplayPoint,
|
||||||
style: EditorStyle,
|
style: EditorStyle,
|
||||||
cx: &AppContext,
|
cx: &mut RenderContext<Editor>,
|
||||||
) -> Option<(DisplayPoint, ElementBox)> {
|
) -> Option<(DisplayPoint, ElementBox)> {
|
||||||
self.context_menu
|
self.context_menu
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -1024,8 +1024,6 @@ impl Element for EditorElement {
|
|||||||
max_row.saturating_sub(1) as f32,
|
max_row.saturating_sub(1) as f32,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut context_menu = None;
|
|
||||||
let mut code_actions_indicator = None;
|
|
||||||
self.update_view(cx.app, |view, cx| {
|
self.update_view(cx.app, |view, cx| {
|
||||||
let clamped = view.clamp_scroll_left(scroll_max.x());
|
let clamped = view.clamp_scroll_left(scroll_max.x());
|
||||||
let autoscrolled;
|
let autoscrolled;
|
||||||
@ -1045,7 +1043,11 @@ impl Element for EditorElement {
|
|||||||
if clamped || autoscrolled {
|
if clamped || autoscrolled {
|
||||||
snapshot = view.snapshot(cx);
|
snapshot = view.snapshot(cx);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut context_menu = None;
|
||||||
|
let mut code_actions_indicator = None;
|
||||||
|
cx.render(&self.view.upgrade(cx).unwrap(), |view, cx| {
|
||||||
let newest_selection_head = view
|
let newest_selection_head = view
|
||||||
.selections
|
.selections
|
||||||
.newest::<usize>(cx)
|
.newest::<usize>(cx)
|
||||||
|
@ -468,6 +468,26 @@ impl TestAppContext {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn render<F, V, T>(&mut self, handle: &ViewHandle<V>, f: F) -> T
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut V, &mut RenderContext<V>) -> T,
|
||||||
|
V: View,
|
||||||
|
{
|
||||||
|
handle.update(&mut *self.cx.borrow_mut(), |view, cx| {
|
||||||
|
let mut render_cx = RenderContext {
|
||||||
|
app: cx,
|
||||||
|
window_id: handle.window_id(),
|
||||||
|
view_id: handle.id(),
|
||||||
|
view_type: PhantomData,
|
||||||
|
titlebar_height: 0.,
|
||||||
|
hovered_region_id: None,
|
||||||
|
clicked_region_id: None,
|
||||||
|
refreshing: false,
|
||||||
|
};
|
||||||
|
f(view, &mut render_cx)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_async(&self) -> AsyncAppContext {
|
pub fn to_async(&self) -> AsyncAppContext {
|
||||||
AsyncAppContext(self.cx.clone())
|
AsyncAppContext(self.cx.clone())
|
||||||
}
|
}
|
||||||
@ -1756,27 +1776,6 @@ impl MutableAppContext {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_render_context<V: View>(
|
|
||||||
&mut self,
|
|
||||||
window_id: usize,
|
|
||||||
view_id: usize,
|
|
||||||
titlebar_height: f32,
|
|
||||||
hovered_region_id: Option<MouseRegionId>,
|
|
||||||
clicked_region_id: Option<MouseRegionId>,
|
|
||||||
refreshing: bool,
|
|
||||||
) -> RenderContext<V> {
|
|
||||||
RenderContext {
|
|
||||||
app: self,
|
|
||||||
window_id,
|
|
||||||
view_id,
|
|
||||||
view_type: PhantomData,
|
|
||||||
titlebar_height,
|
|
||||||
hovered_region_id,
|
|
||||||
clicked_region_id,
|
|
||||||
refreshing,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_view<T, F>(&mut self, window_id: usize, build_view: F) -> ViewHandle<T>
|
pub fn add_view<T, F>(&mut self, window_id: usize, build_view: F) -> ViewHandle<T>
|
||||||
where
|
where
|
||||||
T: View,
|
T: View,
|
||||||
@ -3429,13 +3428,13 @@ pub struct RenderParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct RenderContext<'a, T: View> {
|
pub struct RenderContext<'a, T: View> {
|
||||||
|
pub(crate) window_id: usize,
|
||||||
|
pub(crate) view_id: usize,
|
||||||
|
pub(crate) view_type: PhantomData<T>,
|
||||||
|
pub(crate) hovered_region_id: Option<MouseRegionId>,
|
||||||
|
pub(crate) clicked_region_id: Option<MouseRegionId>,
|
||||||
pub app: &'a mut MutableAppContext,
|
pub app: &'a mut MutableAppContext,
|
||||||
window_id: usize,
|
|
||||||
view_id: usize,
|
|
||||||
view_type: PhantomData<T>,
|
|
||||||
pub titlebar_height: f32,
|
pub titlebar_height: f32,
|
||||||
hovered_region_id: Option<MouseRegionId>,
|
|
||||||
clicked_region_id: Option<MouseRegionId>,
|
|
||||||
pub refreshing: bool,
|
pub refreshing: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3587,6 +3586,16 @@ impl<V> UpgradeViewHandle for ViewContext<'_, V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V: View> UpgradeViewHandle for RenderContext<'_, V> {
|
||||||
|
fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
|
||||||
|
self.cx.upgrade_view_handle(handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn upgrade_any_view_handle(&self, handle: &AnyWeakViewHandle) -> Option<AnyViewHandle> {
|
||||||
|
self.cx.upgrade_any_view_handle(handle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<V: View> UpdateModel for ViewContext<'_, V> {
|
impl<V: View> UpdateModel for ViewContext<'_, V> {
|
||||||
fn update_model<T: Entity, O>(
|
fn update_model<T: Entity, O>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -5,7 +5,7 @@ use crate::{
|
|||||||
vector::{vec2f, Vector2F},
|
vector::{vec2f, Vector2F},
|
||||||
},
|
},
|
||||||
json::{self, json},
|
json::{self, json},
|
||||||
ElementBox,
|
ElementBox, RenderContext, View,
|
||||||
};
|
};
|
||||||
use json::ToJson;
|
use json::ToJson;
|
||||||
use std::{cell::RefCell, cmp, ops::Range, rc::Rc};
|
use std::{cell::RefCell, cmp, ops::Range, rc::Rc};
|
||||||
@ -41,27 +41,40 @@ pub struct LayoutState {
|
|||||||
items: Vec<ElementBox>,
|
items: Vec<ElementBox>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UniformList<F>
|
pub struct UniformList {
|
||||||
where
|
|
||||||
F: Fn(Range<usize>, &mut Vec<ElementBox>, &mut LayoutContext),
|
|
||||||
{
|
|
||||||
state: UniformListState,
|
state: UniformListState,
|
||||||
item_count: usize,
|
item_count: usize,
|
||||||
append_items: F,
|
append_items: Box<dyn Fn(Range<usize>, &mut Vec<ElementBox>, &mut LayoutContext) -> bool>,
|
||||||
padding_top: f32,
|
padding_top: f32,
|
||||||
padding_bottom: f32,
|
padding_bottom: f32,
|
||||||
get_width_from_item: Option<usize>,
|
get_width_from_item: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F> UniformList<F>
|
impl UniformList {
|
||||||
where
|
pub fn new<F, V>(
|
||||||
F: Fn(Range<usize>, &mut Vec<ElementBox>, &mut LayoutContext),
|
state: UniformListState,
|
||||||
{
|
item_count: usize,
|
||||||
pub fn new(state: UniformListState, item_count: usize, append_items: F) -> Self {
|
cx: &mut RenderContext<V>,
|
||||||
|
append_items: F,
|
||||||
|
) -> Self
|
||||||
|
where
|
||||||
|
V: View,
|
||||||
|
F: 'static + Fn(&mut V, Range<usize>, &mut Vec<ElementBox>, &mut RenderContext<V>),
|
||||||
|
{
|
||||||
|
let handle = cx.handle();
|
||||||
Self {
|
Self {
|
||||||
state,
|
state,
|
||||||
item_count,
|
item_count,
|
||||||
append_items,
|
append_items: Box::new(move |range, items, cx| {
|
||||||
|
if let Some(handle) = handle.upgrade(cx) {
|
||||||
|
cx.render(&handle, |view, cx| {
|
||||||
|
append_items(view, range, items, cx);
|
||||||
|
});
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}),
|
||||||
padding_top: 0.,
|
padding_top: 0.,
|
||||||
padding_bottom: 0.,
|
padding_bottom: 0.,
|
||||||
get_width_from_item: None,
|
get_width_from_item: None,
|
||||||
@ -144,10 +157,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F> Element for UniformList<F>
|
impl Element for UniformList {
|
||||||
where
|
|
||||||
F: Fn(Range<usize>, &mut Vec<ElementBox>, &mut LayoutContext),
|
|
||||||
{
|
|
||||||
type LayoutState = LayoutState;
|
type LayoutState = LayoutState;
|
||||||
type PaintState = ();
|
type PaintState = ();
|
||||||
|
|
||||||
|
@ -9,13 +9,14 @@ use crate::{
|
|||||||
text_layout::TextLayoutCache,
|
text_layout::TextLayoutCache,
|
||||||
Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox,
|
Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox,
|
||||||
ElementStateContext, Entity, FontSystem, ModelHandle, MouseRegion, MouseRegionId, ReadModel,
|
ElementStateContext, Entity, FontSystem, ModelHandle, MouseRegion, MouseRegionId, ReadModel,
|
||||||
ReadView, RenderParams, Scene, UpgradeModelHandle, UpgradeViewHandle, View, ViewHandle,
|
ReadView, RenderContext, RenderParams, Scene, UpgradeModelHandle, UpgradeViewHandle, View,
|
||||||
WeakModelHandle, WeakViewHandle,
|
ViewHandle, WeakModelHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use pathfinder_geometry::vector::{vec2f, Vector2F};
|
use pathfinder_geometry::vector::{vec2f, Vector2F};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
|
marker::PhantomData,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
@ -172,12 +173,15 @@ impl Presenter {
|
|||||||
LayoutContext {
|
LayoutContext {
|
||||||
rendered_views: &mut self.rendered_views,
|
rendered_views: &mut self.rendered_views,
|
||||||
parents: &mut self.parents,
|
parents: &mut self.parents,
|
||||||
refreshing,
|
|
||||||
font_cache: &self.font_cache,
|
font_cache: &self.font_cache,
|
||||||
font_system: cx.platform().fonts(),
|
font_system: cx.platform().fonts(),
|
||||||
text_layout_cache: &self.text_layout_cache,
|
text_layout_cache: &self.text_layout_cache,
|
||||||
asset_cache: &self.asset_cache,
|
asset_cache: &self.asset_cache,
|
||||||
view_stack: Vec::new(),
|
view_stack: Vec::new(),
|
||||||
|
refreshing,
|
||||||
|
hovered_region_id: self.hovered_region_id,
|
||||||
|
clicked_region_id: self.clicked_region.as_ref().map(MouseRegion::id),
|
||||||
|
titlebar_height: self.titlebar_height,
|
||||||
app: cx,
|
app: cx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -342,12 +346,15 @@ pub struct LayoutContext<'a> {
|
|||||||
rendered_views: &'a mut HashMap<usize, ElementBox>,
|
rendered_views: &'a mut HashMap<usize, ElementBox>,
|
||||||
parents: &'a mut HashMap<usize, usize>,
|
parents: &'a mut HashMap<usize, usize>,
|
||||||
view_stack: Vec<usize>,
|
view_stack: Vec<usize>,
|
||||||
pub refreshing: bool,
|
|
||||||
pub font_cache: &'a Arc<FontCache>,
|
pub font_cache: &'a Arc<FontCache>,
|
||||||
pub font_system: Arc<dyn FontSystem>,
|
pub font_system: Arc<dyn FontSystem>,
|
||||||
pub text_layout_cache: &'a TextLayoutCache,
|
pub text_layout_cache: &'a TextLayoutCache,
|
||||||
pub asset_cache: &'a AssetCache,
|
pub asset_cache: &'a AssetCache,
|
||||||
pub app: &'a mut MutableAppContext,
|
pub app: &'a mut MutableAppContext,
|
||||||
|
pub refreshing: bool,
|
||||||
|
titlebar_height: f32,
|
||||||
|
hovered_region_id: Option<MouseRegionId>,
|
||||||
|
clicked_region_id: Option<MouseRegionId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> LayoutContext<'a> {
|
impl<'a> LayoutContext<'a> {
|
||||||
@ -362,6 +369,26 @@ impl<'a> LayoutContext<'a> {
|
|||||||
self.view_stack.pop();
|
self.view_stack.pop();
|
||||||
size
|
size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn render<F, V, T>(&mut self, handle: &ViewHandle<V>, f: F) -> T
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut V, &mut RenderContext<V>) -> T,
|
||||||
|
V: View,
|
||||||
|
{
|
||||||
|
handle.update(self.app, |view, cx| {
|
||||||
|
let mut render_cx = RenderContext {
|
||||||
|
app: cx,
|
||||||
|
window_id: handle.window_id(),
|
||||||
|
view_id: handle.id(),
|
||||||
|
view_type: PhantomData,
|
||||||
|
titlebar_height: self.titlebar_height,
|
||||||
|
hovered_region_id: self.hovered_region_id,
|
||||||
|
clicked_region_id: self.clicked_region_id,
|
||||||
|
refreshing: self.refreshing,
|
||||||
|
};
|
||||||
|
f(view, &mut render_cx)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Deref for LayoutContext<'a> {
|
impl<'a> Deref for LayoutContext<'a> {
|
||||||
|
@ -123,7 +123,6 @@ impl View for Select {
|
|||||||
.boxed(),
|
.boxed(),
|
||||||
);
|
);
|
||||||
if self.is_open {
|
if self.is_open {
|
||||||
let handle = self.handle.clone();
|
|
||||||
result.add_child(
|
result.add_child(
|
||||||
Overlay::new(
|
Overlay::new(
|
||||||
Container::new(
|
Container::new(
|
||||||
@ -131,9 +130,8 @@ impl View for Select {
|
|||||||
UniformList::new(
|
UniformList::new(
|
||||||
self.list_state.clone(),
|
self.list_state.clone(),
|
||||||
self.item_count,
|
self.item_count,
|
||||||
move |mut range, items, cx| {
|
cx,
|
||||||
let handle = handle.upgrade(cx).unwrap();
|
move |this, mut range, items, cx| {
|
||||||
let this = handle.read(cx);
|
|
||||||
let selected_item_ix = this.selected_item_ix;
|
let selected_item_ix = this.selected_item_ix;
|
||||||
range.end = range.end.min(this.item_count);
|
range.end = range.end.min(this.item_count);
|
||||||
items.extend(range.map(|ix| {
|
items.extend(range.map(|ix| {
|
||||||
@ -141,7 +139,7 @@ impl View for Select {
|
|||||||
ix,
|
ix,
|
||||||
cx,
|
cx,
|
||||||
|mouse_state, cx| {
|
|mouse_state, cx| {
|
||||||
(handle.read(cx).render_item)(
|
(this.render_item)(
|
||||||
ix,
|
ix,
|
||||||
if ix == selected_item_ix {
|
if ix == selected_item_ix {
|
||||||
ItemType::Selected
|
ItemType::Selected
|
||||||
|
@ -54,6 +54,7 @@ impl<D: PickerDelegate> View for Picker<D> {
|
|||||||
|
|
||||||
fn render(&mut self, cx: &mut RenderContext<Self>) -> gpui::ElementBox {
|
fn render(&mut self, cx: &mut RenderContext<Self>) -> gpui::ElementBox {
|
||||||
let settings = cx.global::<Settings>();
|
let settings = cx.global::<Settings>();
|
||||||
|
let container_style = settings.theme.picker.container;
|
||||||
let delegate = self.delegate.clone();
|
let delegate = self.delegate.clone();
|
||||||
let match_count = if let Some(delegate) = delegate.upgrade(cx.app) {
|
let match_count = if let Some(delegate) = delegate.upgrade(cx.app) {
|
||||||
delegate.read(cx).match_count()
|
delegate.read(cx).match_count()
|
||||||
@ -80,8 +81,9 @@ impl<D: PickerDelegate> View for Picker<D> {
|
|||||||
UniformList::new(
|
UniformList::new(
|
||||||
self.list_state.clone(),
|
self.list_state.clone(),
|
||||||
match_count,
|
match_count,
|
||||||
move |mut range, items, cx| {
|
cx,
|
||||||
let delegate = delegate.upgrade(cx).unwrap();
|
move |this, mut range, items, cx| {
|
||||||
|
let delegate = this.delegate.upgrade(cx).unwrap();
|
||||||
let selected_ix = delegate.read(cx).selected_index();
|
let selected_ix = delegate.read(cx).selected_index();
|
||||||
range.end = cmp::min(range.end, delegate.read(cx).match_count());
|
range.end = cmp::min(range.end, delegate.read(cx).match_count());
|
||||||
items.extend(range.map(move |ix| {
|
items.extend(range.map(move |ix| {
|
||||||
@ -103,7 +105,7 @@ impl<D: PickerDelegate> View for Picker<D> {
|
|||||||
.boxed(),
|
.boxed(),
|
||||||
)
|
)
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(settings.theme.picker.container)
|
.with_style(container_style)
|
||||||
.constrained()
|
.constrained()
|
||||||
.with_max_width(self.max_size.x())
|
.with_max_width(self.max_size.x())
|
||||||
.with_max_height(self.max_size.y())
|
.with_max_height(self.max_size.y())
|
||||||
|
@ -9,8 +9,8 @@ use gpui::{
|
|||||||
},
|
},
|
||||||
impl_internal_actions, keymap,
|
impl_internal_actions, keymap,
|
||||||
platform::CursorStyle,
|
platform::CursorStyle,
|
||||||
AppContext, Element, ElementBox, Entity, ModelHandle, MutableAppContext, PromptLevel, Task,
|
AppContext, Element, ElementBox, Entity, ModelHandle, MutableAppContext, PromptLevel,
|
||||||
View, ViewContext, ViewHandle, WeakViewHandle,
|
RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use project::{Entry, EntryKind, Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId};
|
use project::{Entry, EntryKind, Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId};
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
@ -706,8 +706,8 @@ impl ProjectPanel {
|
|||||||
fn for_each_visible_entry(
|
fn for_each_visible_entry(
|
||||||
&self,
|
&self,
|
||||||
range: Range<usize>,
|
range: Range<usize>,
|
||||||
cx: &mut ViewContext<ProjectPanel>,
|
cx: &mut RenderContext<ProjectPanel>,
|
||||||
mut callback: impl FnMut(ProjectEntryId, EntryDetails, &mut ViewContext<ProjectPanel>),
|
mut callback: impl FnMut(ProjectEntryId, EntryDetails, &mut RenderContext<ProjectPanel>),
|
||||||
) {
|
) {
|
||||||
let mut ix = 0;
|
let mut ix = 0;
|
||||||
for (worktree_id, visible_worktree_entries) in &self.visible_entries {
|
for (worktree_id, visible_worktree_entries) in &self.visible_entries {
|
||||||
@ -780,7 +780,7 @@ impl ProjectPanel {
|
|||||||
details: EntryDetails,
|
details: EntryDetails,
|
||||||
editor: &ViewHandle<Editor>,
|
editor: &ViewHandle<Editor>,
|
||||||
theme: &theme::ProjectPanel,
|
theme: &theme::ProjectPanel,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut RenderContext<Self>,
|
||||||
) -> ElementBox {
|
) -> ElementBox {
|
||||||
let kind = details.kind;
|
let kind = details.kind;
|
||||||
let show_editor = details.is_editing && !details.is_processing;
|
let show_editor = details.is_editing && !details.is_processing;
|
||||||
@ -861,31 +861,28 @@ impl View for ProjectPanel {
|
|||||||
"ProjectPanel"
|
"ProjectPanel"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> gpui::ElementBox {
|
fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> gpui::ElementBox {
|
||||||
let theme = &cx.global::<Settings>().theme.project_panel;
|
let theme = &cx.global::<Settings>().theme.project_panel;
|
||||||
let mut container_style = theme.container;
|
let mut container_style = theme.container;
|
||||||
let padding = std::mem::take(&mut container_style.padding);
|
let padding = std::mem::take(&mut container_style.padding);
|
||||||
let handle = self.handle.clone();
|
|
||||||
UniformList::new(
|
UniformList::new(
|
||||||
self.list.clone(),
|
self.list.clone(),
|
||||||
self.visible_entries
|
self.visible_entries
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, worktree_entries)| worktree_entries.len())
|
.map(|(_, worktree_entries)| worktree_entries.len())
|
||||||
.sum(),
|
.sum(),
|
||||||
move |range, items, cx| {
|
cx,
|
||||||
|
move |this, range, items, cx| {
|
||||||
let theme = cx.global::<Settings>().theme.clone();
|
let theme = cx.global::<Settings>().theme.clone();
|
||||||
let this = handle.upgrade(cx).unwrap();
|
this.for_each_visible_entry(range.clone(), cx, |id, details, cx| {
|
||||||
this.update(cx.app, |this, cx| {
|
items.push(Self::render_entry(
|
||||||
this.for_each_visible_entry(range.clone(), cx, |id, details, cx| {
|
id,
|
||||||
items.push(Self::render_entry(
|
details,
|
||||||
id,
|
&this.filename_editor,
|
||||||
details,
|
&theme.project_panel,
|
||||||
&this.filename_editor,
|
cx,
|
||||||
&theme.project_panel,
|
));
|
||||||
cx,
|
});
|
||||||
));
|
|
||||||
});
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.with_padding_top(padding.top)
|
.with_padding_top(padding.top)
|
||||||
@ -1343,7 +1340,7 @@ mod tests {
|
|||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
let mut project_entries = HashSet::new();
|
let mut project_entries = HashSet::new();
|
||||||
let mut has_editor = false;
|
let mut has_editor = false;
|
||||||
panel.update(cx, |panel, cx| {
|
cx.render(panel, |panel, cx| {
|
||||||
panel.for_each_visible_entry(range, cx, |project_entry, details, _| {
|
panel.for_each_visible_entry(range, cx, |project_entry, details, _| {
|
||||||
if details.is_editing {
|
if details.is_editing {
|
||||||
assert!(!has_editor, "duplicate editor entry");
|
assert!(!has_editor, "duplicate editor entry");
|
||||||
|
Loading…
Reference in New Issue
Block a user