Skip to content

Commit

Permalink
refactor(core): 💡 Remove temporary code and unify the use of BuildCtx
Browse files Browse the repository at this point in the history
  • Loading branch information
M-Adoo committed Sep 15, 2023
1 parent cfa7faf commit e374819
Show file tree
Hide file tree
Showing 28 changed files with 123 additions and 148 deletions.
2 changes: 1 addition & 1 deletion core/src/animation/animate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ where
pub from: <S::State as StateReader>::Value,
#[declare(skip)]
running_info: Option<AnimateInfo<<S::State as StateReader>::Value>>,
#[declare(skip, default = ctx.window().id())]
#[declare(skip, default = ctx!().window().id())]
window_id: WindowId,
}

Expand Down
4 changes: 2 additions & 2 deletions core/src/builtin_widgets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,15 +223,15 @@ impl<T: ComposeChild + 'static> ComposeChild for FatObj<T> {
}

impl<T: SingleParent + 'static> SingleParent for FatObj<T> {
fn append_child(self, child: WidgetId, ctx: &mut BuildCtx) -> WidgetId {
fn append_child(self, child: WidgetId, ctx: &BuildCtx) -> WidgetId {
let Self { host, builtin } = self;
let p = host.append_child(child, ctx);
builtin.compose_with_host(p.into(), ctx).build(ctx)
}
}

impl<T: MultiParent + 'static> MultiParent for FatObj<T> {
fn append_children(self, children: Vec<WidgetId>, ctx: &mut BuildCtx) -> WidgetId {
fn append_children(self, children: Vec<WidgetId>, ctx: &BuildCtx) -> WidgetId {
let Self { host, builtin } = self;
let host = host.append_children(children, ctx);
builtin.compose_with_host(host.into(), ctx).build(ctx)
Expand Down
18 changes: 10 additions & 8 deletions core/src/builtin_widgets/theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//! to app-wide or particular part of the application.
use crate::{fill_svgs, impl_query_self_only, prelude::*, widget::StrictBuilder};
use ribir_algo::Sc;
pub use ribir_algo::{CowArc, ShareResource};
use ribir_geom::Size;
use ribir_macros::Declare2;
Expand Down Expand Up @@ -68,7 +69,7 @@ pub enum Theme {

#[derive(Declare2)]
pub struct ThemeWidget {
pub theme: Rc<Theme>,
pub theme: Sc<Theme>,
}

impl ComposeChild for ThemeWidget {
Expand All @@ -77,17 +78,18 @@ impl ComposeChild for ThemeWidget {
fn compose_child(this: State<Self>, child: Self::Child) -> Widget {
use crate::prelude::*;
FnWidget::new(move |ctx| {
let ctx = ctx.force_as_mut();
let theme = this.read().theme.clone();

AppCtx::load_font_from_theme(&theme);
ctx.push_theme(theme.clone());

let mut themes = ctx.themes().clone();
themes.push(theme.clone());

let p = DataWidget::new(Box::new(Void), theme).strict_build(ctx);
let old = ctx.force_as_mut().reset_ctx_from(Some(p));
let c = child.build(ctx);
// shadow the context with the theme.
let ctx = BuildCtx::new_with_data(Some(p), ctx.tree, themes);
let c = child.build(&ctx);
ctx.append_child(p, c);
ctx.force_as_mut().reset_ctx_from(old);
ctx.pop_theme();

p
})
.into()
Expand Down
4 changes: 2 additions & 2 deletions core/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ mod layout_ctx;
mod widget_ctx;
pub use layout_ctx::*;
pub use widget_ctx::*;
pub(crate) mod build_context;
pub use build_context::BuildCtx;
pub(crate) mod build_ctx;
pub use build_ctx::BuildCtx;
pub mod app_ctx;
pub use app_ctx::*;
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
use ribir_algo::Sc;

use crate::{
prelude::*,
widget::{widget_id::new_node, WidgetTree},
window::{DelayEvent, WindowId},
};
use std::{
cell::{Ref, RefCell, UnsafeCell},
cell::{OnceCell, Ref, RefCell},
ops::Deref,
rc::Rc,
};

/// A context provide during build the widget tree.
pub struct BuildCtx<'a> {
// tmp `UnsafeCell` before use `BuildCtx` as mutable reference.
pub(crate) themes: UnsafeCell<Option<Vec<Rc<Theme>>>>,
pub(crate) themes: OnceCell<Vec<Sc<Theme>>>,
/// The widget which this `BuildCtx` is created from. It's not means this
/// is the parent of the widget which is builded by this `BuildCtx`.
ctx_from: Option<WidgetId>,
Expand Down Expand Up @@ -43,19 +44,27 @@ impl<'a> BuildCtx<'a> {
}
}

pub fn reset_ctx_from(&mut self, reset: Option<WidgetId>) -> Option<WidgetId> {
std::mem::replace(&mut self.ctx_from, reset)
}

#[inline]
pub(crate) fn new(from: Option<WidgetId>, tree: &'a RefCell<WidgetTree>) -> Self {
Self {
themes: UnsafeCell::new(None),
themes: OnceCell::new(),
ctx_from: from,
tree,
}
}

pub(crate) fn new_with_data(
from: Option<WidgetId>,
tree: &'a RefCell<WidgetTree>,
data: Vec<Sc<Theme>>,
) -> Self {
let themes: OnceCell<Vec<Sc<Theme>>> = OnceCell::new();
// Safety: we just create the `OnceCell` and it's empty.
unsafe { themes.set(data).unwrap_unchecked() };

Self { themes, ctx_from: from, tree }
}

pub(crate) fn find_cfg<T>(&self, f: impl Fn(&Theme) -> Option<&T>) -> Option<&T> {
for t in self.themes().iter().rev() {
let v = f(t);
Expand All @@ -77,12 +86,12 @@ impl<'a> BuildCtx<'a> {
new_node(&mut self.tree.borrow_mut().arena, widget)
}

pub(crate) fn append_child(&mut self, parent: WidgetId, child: WidgetId) {
pub(crate) fn append_child(&self, parent: WidgetId, child: WidgetId) {
parent.append(child, &mut self.tree.borrow_mut().arena);
}

/// Insert `next` after `prev`
pub(crate) fn insert_after(&mut self, prev: WidgetId, next: WidgetId) {
pub(crate) fn insert_after(&self, prev: WidgetId, next: WidgetId) {
prev.insert_after(next, &mut self.tree.borrow_mut().arena);
}

Expand Down Expand Up @@ -124,43 +133,23 @@ impl<'a> BuildCtx<'a> {
.add_delay_event(DelayEvent::Disposed { id, parent });
}

pub(crate) fn mark_dirty(&mut self, id: WidgetId) { self.tree.borrow_mut().mark_dirty(id); }

#[inline]
pub(crate) fn push_theme(&self, theme: Rc<Theme>) { self.themes().push(theme); }

#[inline]
pub(crate) fn pop_theme(&self) { self.themes().pop(); }

/// todo: tmp code
/// because we use `BuildCtx` as reference now, but we need to use it as
/// mutable reference. Do a unsafe cast here, and remove it when we use
/// `BuildCtx` as mutable reference in `Widget`
#[allow(clippy::mut_from_ref)]
pub(crate) fn force_as_mut(&self) -> &mut Self {
#[allow(clippy::cast_ref_to_mut)]
unsafe {
&mut *(self as *const Self as *mut Self)
}
}
pub(crate) fn mark_dirty(&self, id: WidgetId) { self.tree.borrow_mut().mark_dirty(id); }

#[allow(clippy::mut_from_ref)]
fn themes(&self) -> &mut Vec<Rc<Theme>> {
let this = self.force_as_mut();
unsafe { &mut *this.themes.get() }.get_or_insert_with(|| {
pub(crate) fn themes(&self) -> &Vec<Sc<Theme>> {
self.themes.get_or_init(|| {
let mut themes = vec![];
let Some(p) = self.ctx_from else { return themes };

let arena = &this.tree.borrow().arena;
let arena = &self.tree.borrow().arena;
p.ancestors(arena).any(|p| {
p.assert_get(arena).query_all_type(
|t: &Rc<Theme>| {
|t: &Sc<Theme>| {
themes.push(t.clone());
matches!(t.deref(), Theme::Inherit(_))
},
QueryOrder::InnerFirst,
);
matches!(themes.last().map(Rc::deref), Some(Theme::Full(_)))
matches!(themes.last().map(Sc::deref), Some(Theme::Full(_)))
});
themes
})
Expand Down Expand Up @@ -191,7 +180,7 @@ mod tests {
#[derive(Default, Clone)]
struct LightDarkThemes(Rc<RefCell<Vec<Theme>>>);

let themes: Stateful<Vec<Rc<Theme>>> = Stateful::new(vec![]);
let themes: Stateful<Vec<Sc<Theme>>> = Stateful::new(vec![]);
let c_themes = themes.clone_writer();
let light_palette = Palette {
brightness: Brightness::Light,
Expand All @@ -203,15 +192,15 @@ mod tests {
};
let light_dark = fn_widget! {
@ThemeWidget {
theme: Rc::new(Theme::Inherit(InheritTheme {
theme: Sc::new(Theme::Inherit(InheritTheme {
palette: Some(Rc::new(light_palette)),
..<_>::default()

})),
@MockBox {
size: INFINITY_SIZE,
@ThemeWidget {
theme: Rc::new(Theme::Inherit(InheritTheme {
theme: Sc::new(Theme::Inherit(InheritTheme {
palette: Some(Rc::new(dark_palette)),
..<_>::default()
})),
Expand Down
2 changes: 1 addition & 1 deletion core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(decl_macro)]
#![feature(decl_macro, once_cell)]
#![cfg_attr(test, feature(mutex_unpoison, test))]

#[macro_use]
Expand Down
19 changes: 8 additions & 11 deletions core/src/pipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ impl<W: Into<Widget> + 'static> StrictBuilder for Pipe<W> {
let wnd = ctx.window();
AppCtx::spawn_local(async move { wnd.remove_regenerating_mark(id) }).unwrap();

let ctx = ctx.force_as_mut();
if !ctx.window().is_in_another_regenerating(id) {
let new_id = v.into().build(ctx);

Expand Down Expand Up @@ -171,7 +170,7 @@ impl<W: Into<Widget> + 'static> WidgetBuilder for Pipe<Option<W>> {
}

impl<W: SingleParent + 'static> SingleParent for Pipe<W> {
fn append_child(self, child: WidgetId, ctx: &mut BuildCtx) -> WidgetId {
fn append_child(self, child: WidgetId, ctx: &BuildCtx) -> WidgetId {
let (v, modifies) = self.unzip();
let p = v.append_child(child, ctx);
let rg = half_to_close_interval(p..child, &ctx.tree.borrow());
Expand All @@ -184,7 +183,7 @@ impl<W: SingleParent + 'static> SingleParent for Pipe<W> {
}

impl<W: MultiParent + StrictBuilder + 'static> MultiParent for Pipe<W> {
fn append_children(self, children: Vec<WidgetId>, ctx: &mut BuildCtx) -> WidgetId {
fn append_children(self, children: Vec<WidgetId>, ctx: &BuildCtx) -> WidgetId {
// if children is empty, we can let the pipe parent as the whole subtree.
if children.is_empty() {
self.strict_build(ctx)
Expand All @@ -203,7 +202,7 @@ impl<W: MultiParent + StrictBuilder + 'static> MultiParent for Pipe<W> {
}

impl<W: SingleParent + Into<Widget> + 'static> SingleParent for Pipe<Option<W>> {
fn append_child(self, child: WidgetId, ctx: &mut BuildCtx) -> WidgetId {
fn append_child(self, child: WidgetId, ctx: &BuildCtx) -> WidgetId {
self
.map(|p| -> Box<dyn BoxedSingleParent> {
if let Some(p) = p {
Expand All @@ -225,8 +224,8 @@ fn update_pipe_parent<W: 'static>(
parent: Range<WidgetId>,
// transplant the children of the old parent to the new widget.
modifies: BoxOp<'static, (ModifyScope, W), Infallible>,
ctx: &mut BuildCtx,
transplant: impl Fn(W, WidgetId, &mut BuildCtx) -> WidgetId + 'static,
ctx: &BuildCtx,
transplant: impl Fn(W, WidgetId, &BuildCtx) -> WidgetId + 'static,
) {
let id_share = Sc::new(RefCell::new(parent.clone()));
let id_share2 = id_share.clone();
Expand All @@ -243,7 +242,6 @@ fn update_pipe_parent<W: 'static>(
.sample(new_frame_sampler!(ctx))
.subscribe(move |(_, v)| {
handle.with_ctx(|ctx| {
let ctx = ctx.force_as_mut();
let rg = id_share.borrow().clone();

let wnd = ctx.window();
Expand All @@ -253,7 +251,7 @@ fn update_pipe_parent<W: 'static>(

if !ctx.window().is_in_another_regenerating(rg.start) {
let first_child = rg.end.first_child(&ctx.tree.borrow().arena).unwrap();
let p = transplant(v, rg.end, ctx.force_as_mut());
let p = transplant(v, rg.end, ctx);
let new_rg = half_to_close_interval(p..first_child, &ctx.tree.borrow());

update_key_status_single(rg.start, new_rg.start, ctx);
Expand All @@ -276,14 +274,14 @@ fn update_pipe_parent<W: 'static>(
}

impl<W: 'static> Pipe<W> {
pub(crate) fn build_multi(self, vec: &mut Vec<WidgetId>, ctx: &mut BuildCtx)
pub(crate) fn build_multi(self, vec: &mut Vec<WidgetId>, ctx: &BuildCtx)
where
W: IntoIterator,
W::Item: WidgetBuilder,
{
fn build_multi(
v: impl IntoIterator<Item = impl WidgetBuilder>,
ctx: &mut BuildCtx,
ctx: &BuildCtx,
) -> Vec<WidgetId> {
let mut ids = v.into_iter().map(|w| w.build(ctx)).collect::<Vec<_>>();

Expand Down Expand Up @@ -320,7 +318,6 @@ impl<W: 'static> Pipe<W> {
.box_it()
.subscribe(move |(_, m)| {
handle.with_ctx(|ctx| {
let ctx = ctx.force_as_mut();
let mut old = ids_share.borrow_mut();
let removed_subtree = old.clone();

Expand Down
4 changes: 3 additions & 1 deletion core/src/widget.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub(crate) use crate::widget_tree::*;
use crate::{context::*, prelude::*};
use ribir_algo::ShareResource;
use ribir_algo::{Sc, ShareResource};
use rxrust::subscription::{BoxSubscription, SubscriptionGuard};

use std::rc::Rc;
Expand Down Expand Up @@ -372,6 +372,8 @@ impl_proxy_query!(paths [deref()], ShareResource<T>, <T>, where T: Render + 'st
impl_proxy_render!(proxy deref(), ShareResource<T>, <T>, where T: Render + 'static);
impl_proxy_query!(paths [deref()], Rc<W>, <W>, where W: Query + 'static);
impl_proxy_render!(proxy deref(), Rc<W>, <W>, where W: Render + 'static);
impl_proxy_query!(paths [deref()], Sc<W>, <W>, where W: Query + 'static);
impl_proxy_render!(proxy deref(), Sc<W>, <W>, where W: Render + 'static);

impl_query_self_only!(Vec<SubscriptionGuard<BoxSubscription<'static>>>);

Expand Down
Loading

0 comments on commit e374819

Please sign in to comment.