From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 609391FF179 for ; Wed, 10 Dec 2025 11:48:21 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id B5A5D1847D; Wed, 10 Dec 2025 11:49:01 +0100 (CET) From: Dominik Csapak To: yew-devel@lists.proxmox.com Date: Wed, 10 Dec 2025 11:48:50 +0100 Message-ID: <20251210104856.1698157-4-d.csapak@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251210104856.1698157-1-d.csapak@proxmox.com> References: <20251210104856.1698157-1-d.csapak@proxmox.com> MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.031 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [yew-devel] [PATCH yew-widget-toolkit 3/3] props: make RenderFn's return type generic X-BeenThere: yew-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Yew framework devel list at Proxmox List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Yew framework devel list at Proxmox Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: yew-devel-bounces@lists.proxmox.com Sender: "yew-devel" and use that with the type `String` instead of our TextRenderFn, that is now obsolete. This not only gets rid of a trait, but also allows us to have more generic render functions in use, e.g. if some component needs a render function that returns e.g. a `Dialog` to do something with it, which would now be possible. By defining the generic type `OUT` as `Html` by default, we don't break compatibility with existing users. This is now very similar to yew's `Callback` type, but it just gives a reference to the function instead of an owned type. Signed-off-by: Dominik Csapak --- src/props/mod.rs | 5 +-- src/props/render_function.rs | 81 ++++++------------------------------ src/touch/material_app.rs | 10 ++--- src/widget/catalog_loader.rs | 6 +-- src/widget/desktop_app.rs | 6 +-- src/widget/meter.rs | 6 +-- src/widget/theme_loader.rs | 6 +-- 7 files changed, 30 insertions(+), 90 deletions(-) diff --git a/src/props/mod.rs b/src/props/mod.rs index db5cc52..254cb4e 100644 --- a/src/props/mod.rs +++ b/src/props/mod.rs @@ -200,10 +200,7 @@ mod padding; pub use padding::CssPaddingBuilder; mod render_function; -pub use render_function::{ - BuilderFn, IntoOptionalBuilderFn, IntoOptionalRenderFn, IntoOptionalTextRenderFn, RenderFn, - TextRenderFn, -}; +pub use render_function::{BuilderFn, IntoOptionalBuilderFn, IntoOptionalRenderFn, RenderFn}; mod sorter_function; pub use sorter_function::{IntoSorterFn, SorterFn}; diff --git a/src/props/render_function.rs b/src/props/render_function.rs index 8773c8b..dd5632d 100644 --- a/src/props/render_function.rs +++ b/src/props/render_function.rs @@ -1,4 +1,3 @@ -use std::fmt::Display; use std::rc::Rc; use derivative::Derivative; @@ -10,100 +9,44 @@ use yew::Html; /// Wraps `Rc` around `Fn` so it can be passed as a prop. #[derive(Derivative)] #[derivative(Clone(bound = ""), PartialEq(bound = ""))] -pub struct RenderFn( - #[derivative(PartialEq(compare_with = "Rc::ptr_eq"))] Rc Html>, +pub struct RenderFn( + #[derivative(PartialEq(compare_with = "Rc::ptr_eq"))] Rc OUT>, ); -impl RenderFn { +impl RenderFn { /// Creates a new [`RenderFn`] - pub fn new(renderer: impl 'static + Fn(&T) -> Html) -> Self { + pub fn new(renderer: impl 'static + Fn(&IN) -> OUT) -> Self { Self(Rc::new(renderer)) } /// Apply the render function - pub fn apply(&self, data: &T) -> Html { + pub fn apply(&self, data: &IN) -> OUT { (self.0)(data) } } -impl Html> From for RenderFn { +impl OUT> From for RenderFn { fn from(f: F) -> Self { RenderFn::new(f) } } /// Helper trait to create an optional [RenderFn] property. -pub trait IntoOptionalRenderFn { - fn into_optional_render_fn(self) -> Option>; +pub trait IntoOptionalRenderFn { + fn into_optional_render_fn(self) -> Option>; } -impl>> IntoOptionalRenderFn for R { - fn into_optional_render_fn(self) -> Option> { +impl>> IntoOptionalRenderFn for R { + fn into_optional_render_fn(self) -> Option> { Some(self.into()) } } -impl>> IntoOptionalRenderFn for Option { - fn into_optional_render_fn(self) -> Option> { +impl>> IntoOptionalRenderFn for Option { + fn into_optional_render_fn(self) -> Option> { self.map(|me| me.into()) } } -/// A [TextRenderFn] function is a callback that transforms data into [String]. -/// -/// Wraps `Rc` around `Fn` so it can be passed as a prop. -#[derive(Derivative)] -#[derivative(Clone(bound = ""), PartialEq(bound = ""))] -pub struct TextRenderFn( - #[derivative(PartialEq(compare_with = "Rc::ptr_eq"))] Rc String>, -); - -impl TextRenderFn { - /// Creates a new [TextRenderFn] - pub fn new(renderer: impl 'static + Fn(&T) -> String) -> Self { - Self(Rc::new(renderer)) - } - /// Apply the render function - pub fn apply(&self, data: &T) -> String { - (self.0)(data) - } -} - -impl String> From for TextRenderFn { - fn from(f: F) -> Self { - TextRenderFn::new(f) - } -} - -/// Helper trait to create an optional [TextRenderFn] property. -/// -/// For types implementing [Display], you can pass 'true' to create -/// a render function whichs uses `to_string()`. -pub trait IntoOptionalTextRenderFn { - fn into_optional_text_render_fn(self) -> Option>; -} - -impl>> IntoOptionalTextRenderFn for R { - fn into_optional_text_render_fn(self) -> Option> { - Some(self.into()) - } -} - -impl>> IntoOptionalTextRenderFn for Option { - fn into_optional_text_render_fn(self) -> Option> { - self.map(|me| me.into()) - } -} - -impl IntoOptionalTextRenderFn for bool { - fn into_optional_text_render_fn(self) -> Option> { - if self { - Some(TextRenderFn::new(|t: &T| t.to_string())) - } else { - None - } - } -} - /// A [BuilderFn] function is a callback that returns a generic type. /// /// Wraps `Rc` around `Fn` so it can be passed as a prop. diff --git a/src/touch/material_app.rs b/src/touch/material_app.rs index 52e7042..26de2b3 100644 --- a/src/touch/material_app.rs +++ b/src/touch/material_app.rs @@ -12,7 +12,7 @@ use yew_router::{history::History, Router}; use pwt_macros::builder; use crate::prelude::*; -use crate::props::{IntoOptionalTextRenderFn, TextRenderFn}; +use crate::props::{IntoOptionalRenderFn, RenderFn}; use crate::state::{NavigationContainer, SharedState, SharedStateObserver}; use crate::touch::{PageAnimationStyle, SnackBarController, SnackBarManager}; use crate::widget::{CatalogLoader, Container, ThemeLoader}; @@ -216,14 +216,14 @@ pub struct MaterialApp { pub page_animation: Option, /// Returns the server side CSS URLs (see [ThemeLoader]). - #[builder_cb(IntoOptionalTextRenderFn, into_optional_text_render_fn, String)] + #[builder_cb(IntoOptionalRenderFn, into_optional_render_fn, String, String)] #[prop_or_default] - pub theme_url_builder: Option>, + pub theme_url_builder: Option>, /// Convert ISO 639-1 language code to server side catalog URLs (see [CatalogLoader]). - #[builder_cb(IntoOptionalTextRenderFn, into_optional_text_render_fn, String)] + #[builder_cb(IntoOptionalRenderFn, into_optional_render_fn, String, String)] #[prop_or_default] - pub catalog_url_builder: Option>, + pub catalog_url_builder: Option>, /// Default language (skip catalog loading for this language) #[builder(IntoPropValue, into_prop_value)] diff --git a/src/widget/catalog_loader.rs b/src/widget/catalog_loader.rs index ef53a05..e8afe90 100644 --- a/src/widget/catalog_loader.rs +++ b/src/widget/catalog_loader.rs @@ -4,7 +4,7 @@ use gettext::Catalog; use yew::html::IntoPropValue; use yew::virtual_dom::{VComp, VNode}; -use crate::props::{IntoOptionalTextRenderFn, TextRenderFn}; +use crate::props::{IntoOptionalRenderFn, RenderFn}; use crate::state::{get_language_info, Language, LanguageObserver}; use crate::widget::rtl_switcher::set_text_direction; use crate::{impl_to_html, prelude::*}; @@ -35,9 +35,9 @@ pub struct CatalogLoader { /// # fn test () -> Callback { /// Callback::from(|lang: String| format!("catalog-{}.mo", lang)) /// # } - #[builder_cb(IntoOptionalTextRenderFn, into_optional_text_render_fn, String)] + #[builder_cb(IntoOptionalRenderFn, into_optional_render_fn, String, String)] #[prop_or_default] - pub url_builder: Option>, + pub url_builder: Option>, /// Default language (skip catalog loading for this language) #[builder(IntoPropValue, into_prop_value)] diff --git a/src/widget/desktop_app.rs b/src/widget/desktop_app.rs index 622b2ed..a7fe20c 100644 --- a/src/widget/desktop_app.rs +++ b/src/widget/desktop_app.rs @@ -7,7 +7,7 @@ use yew_router::Router; use gloo_history::{AnyHistory, HashHistory}; use crate::prelude::*; -use crate::props::{IntoOptionalTextRenderFn, TextRenderFn}; +use crate::props::{IntoOptionalRenderFn, RenderFn}; use crate::state::NavigationContainer; use crate::widget::{CatalogLoader, ThemeLoader}; @@ -41,9 +41,9 @@ pub struct DesktopApp { pub history: Option, /// Convert ISO 639-1 language code to server side catalog URLs (see [CatalogLoader]). - #[builder_cb(IntoOptionalTextRenderFn, into_optional_text_render_fn, String)] + #[builder_cb(IntoOptionalRenderFn, into_optional_render_fn, String, String)] #[prop_or_default] - pub catalog_url_builder: Option>, + pub catalog_url_builder: Option>, /// Default language (skip catalog loading for this language) #[builder(IntoPropValue, into_prop_value)] diff --git a/src/widget/meter.rs b/src/widget/meter.rs index c547a87..cf552cb 100644 --- a/src/widget/meter.rs +++ b/src/widget/meter.rs @@ -7,7 +7,7 @@ use yew::virtual_dom::VTag; use pwt_macros::{builder, widget}; use crate::props::{ - ContainerBuilder, CssLength, IntoOptionalTextRenderFn, IntoVTag, TextRenderFn, WidgetBuilder, + ContainerBuilder, CssLength, IntoOptionalRenderFn, IntoVTag, RenderFn, WidgetBuilder, WidgetStyleBuilder, }; use crate::widget::Container; @@ -64,9 +64,9 @@ pub struct Meter { pub value: f32, /// Show value as text. - #[builder_cb(IntoOptionalTextRenderFn, into_optional_text_render_fn, f32)] + #[builder_cb(IntoOptionalRenderFn, into_optional_render_fn, f32, String)] #[prop_or_default] - pub render_text: Option>, + pub render_text: Option>, /// Determines if the meter value transitions are animated (via CSS) or not. /// It is equivalent to setting the class `pwt-animated`. diff --git a/src/widget/theme_loader.rs b/src/widget/theme_loader.rs index f7baa46..cb4831d 100644 --- a/src/widget/theme_loader.rs +++ b/src/widget/theme_loader.rs @@ -5,7 +5,7 @@ use yew::prelude::*; use yew::virtual_dom::{Key, VComp, VNode}; use crate::impl_to_html; -use crate::props::{IntoOptionalTextRenderFn, TextRenderFn}; +use crate::props::{IntoOptionalRenderFn, RenderFn}; use crate::state::{Theme, ThemeDensity, ThemeObserver}; /// Dynamically load selected theme @@ -23,9 +23,9 @@ pub struct ThemeLoader { /// Returns the server side CSS URL (full path) /// /// Default is "{lc(theme_name)}-yew-style.css". - #[builder_cb(IntoOptionalTextRenderFn, into_optional_text_render_fn, String)] + #[builder_cb(IntoOptionalRenderFn, into_optional_render_fn, String, String)] #[prop_or_default] - pub theme_url_builder: Option>, + pub theme_url_builder: Option>, } impl ThemeLoader { -- 2.47.3 _______________________________________________ yew-devel mailing list yew-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/yew-devel