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
8 changed files with 193 additions and 135 deletions
|
@ -468,6 +468,26 @@ impl TestAppContext {
|
|||
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 {
|
||||
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>
|
||||
where
|
||||
T: View,
|
||||
|
@ -3429,13 +3428,13 @@ pub struct RenderParams {
|
|||
}
|
||||
|
||||
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,
|
||||
window_id: usize,
|
||||
view_id: usize,
|
||||
view_type: PhantomData<T>,
|
||||
pub titlebar_height: f32,
|
||||
hovered_region_id: Option<MouseRegionId>,
|
||||
clicked_region_id: Option<MouseRegionId>,
|
||||
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> {
|
||||
fn update_model<T: Entity, O>(
|
||||
&mut self,
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
|||
vector::{vec2f, Vector2F},
|
||||
},
|
||||
json::{self, json},
|
||||
ElementBox,
|
||||
ElementBox, RenderContext, View,
|
||||
};
|
||||
use json::ToJson;
|
||||
use std::{cell::RefCell, cmp, ops::Range, rc::Rc};
|
||||
|
@ -41,27 +41,40 @@ pub struct LayoutState {
|
|||
items: Vec<ElementBox>,
|
||||
}
|
||||
|
||||
pub struct UniformList<F>
|
||||
where
|
||||
F: Fn(Range<usize>, &mut Vec<ElementBox>, &mut LayoutContext),
|
||||
{
|
||||
pub struct UniformList {
|
||||
state: UniformListState,
|
||||
item_count: usize,
|
||||
append_items: F,
|
||||
append_items: Box<dyn Fn(Range<usize>, &mut Vec<ElementBox>, &mut LayoutContext) -> bool>,
|
||||
padding_top: f32,
|
||||
padding_bottom: f32,
|
||||
get_width_from_item: Option<usize>,
|
||||
}
|
||||
|
||||
impl<F> UniformList<F>
|
||||
where
|
||||
F: Fn(Range<usize>, &mut Vec<ElementBox>, &mut LayoutContext),
|
||||
{
|
||||
pub fn new(state: UniformListState, item_count: usize, append_items: F) -> Self {
|
||||
impl UniformList {
|
||||
pub fn new<F, V>(
|
||||
state: UniformListState,
|
||||
item_count: usize,
|
||||
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 {
|
||||
state,
|
||||
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_bottom: 0.,
|
||||
get_width_from_item: None,
|
||||
|
@ -144,10 +157,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<F> Element for UniformList<F>
|
||||
where
|
||||
F: Fn(Range<usize>, &mut Vec<ElementBox>, &mut LayoutContext),
|
||||
{
|
||||
impl Element for UniformList {
|
||||
type LayoutState = LayoutState;
|
||||
type PaintState = ();
|
||||
|
||||
|
|
|
@ -9,13 +9,14 @@ use crate::{
|
|||
text_layout::TextLayoutCache,
|
||||
Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox,
|
||||
ElementStateContext, Entity, FontSystem, ModelHandle, MouseRegion, MouseRegionId, ReadModel,
|
||||
ReadView, RenderParams, Scene, UpgradeModelHandle, UpgradeViewHandle, View, ViewHandle,
|
||||
WeakModelHandle, WeakViewHandle,
|
||||
ReadView, RenderContext, RenderParams, Scene, UpgradeModelHandle, UpgradeViewHandle, View,
|
||||
ViewHandle, WeakModelHandle, WeakViewHandle,
|
||||
};
|
||||
use pathfinder_geometry::vector::{vec2f, Vector2F};
|
||||
use serde_json::json;
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
marker::PhantomData,
|
||||
ops::{Deref, DerefMut},
|
||||
sync::Arc,
|
||||
};
|
||||
|
@ -172,12 +173,15 @@ impl Presenter {
|
|||
LayoutContext {
|
||||
rendered_views: &mut self.rendered_views,
|
||||
parents: &mut self.parents,
|
||||
refreshing,
|
||||
font_cache: &self.font_cache,
|
||||
font_system: cx.platform().fonts(),
|
||||
text_layout_cache: &self.text_layout_cache,
|
||||
asset_cache: &self.asset_cache,
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
@ -342,12 +346,15 @@ pub struct LayoutContext<'a> {
|
|||
rendered_views: &'a mut HashMap<usize, ElementBox>,
|
||||
parents: &'a mut HashMap<usize, usize>,
|
||||
view_stack: Vec<usize>,
|
||||
pub refreshing: bool,
|
||||
pub font_cache: &'a Arc<FontCache>,
|
||||
pub font_system: Arc<dyn FontSystem>,
|
||||
pub text_layout_cache: &'a TextLayoutCache,
|
||||
pub asset_cache: &'a AssetCache,
|
||||
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> {
|
||||
|
@ -362,6 +369,26 @@ impl<'a> LayoutContext<'a> {
|
|||
self.view_stack.pop();
|
||||
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> {
|
||||
|
|
|
@ -123,7 +123,6 @@ impl View for Select {
|
|||
.boxed(),
|
||||
);
|
||||
if self.is_open {
|
||||
let handle = self.handle.clone();
|
||||
result.add_child(
|
||||
Overlay::new(
|
||||
Container::new(
|
||||
|
@ -131,9 +130,8 @@ impl View for Select {
|
|||
UniformList::new(
|
||||
self.list_state.clone(),
|
||||
self.item_count,
|
||||
move |mut range, items, cx| {
|
||||
let handle = handle.upgrade(cx).unwrap();
|
||||
let this = handle.read(cx);
|
||||
cx,
|
||||
move |this, mut range, items, cx| {
|
||||
let selected_item_ix = this.selected_item_ix;
|
||||
range.end = range.end.min(this.item_count);
|
||||
items.extend(range.map(|ix| {
|
||||
|
@ -141,7 +139,7 @@ impl View for Select {
|
|||
ix,
|
||||
cx,
|
||||
|mouse_state, cx| {
|
||||
(handle.read(cx).render_item)(
|
||||
(this.render_item)(
|
||||
ix,
|
||||
if ix == selected_item_ix {
|
||||
ItemType::Selected
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue