use std::any::type_name;
use std::borrow::Cow;
use std::fmt::{Debug, Formatter};
use std::marker::PhantomData;
use std::sync::Arc;
use crate::{BaseView, DefiningMethod, ObjectRef, PhlowView, ViewInstance};
type TextComputation<T> = dyn for<'a> Fn(&'a T) -> Cow<'a, str> + Send + Sync + 'static;
#[allow(unused)]
pub struct PhlowTextView<T: ?Sized> {
base_view: BaseView,
text_computation: Arc<TextComputation<T>>,
phantom_data: PhantomData<fn() -> T>,
}
impl<T: ?Sized> PhlowTextView<T> {
pub fn new(defining_method: Option<DefiningMethod>) -> Self {
Self {
base_view: BaseView::new(defining_method),
text_computation: Arc::new(|_value| type_name::<T>().into()),
phantom_data: PhantomData,
}
}
pub fn title(mut self, title: impl Into<String>) -> Self {
self.base_view.title = title.into();
self
}
pub fn priority(mut self, priority: usize) -> Self {
self.base_view.priority = priority;
self
}
pub fn text(mut self, text_block: impl Fn(&T) -> String + Send + Sync + 'static) -> Self {
self.text_computation = Arc::new(move |value| Cow::from(text_block(value)));
self
}
pub fn text_ref(mut self, text_block: impl Fn(&T) -> &str + Send + Sync + 'static) -> Self {
self.text_computation = Arc::new(move |value| Cow::from(text_block(value)));
self
}
pub fn compute_text<'a>(&self, object: &'a T) -> Cow<'a, str> {
(self.text_computation)(object)
}
}
#[derive(Debug, Clone)]
pub struct TextViewInstance {
pub base_view: BaseView,
pub text: String,
}
impl ViewInstance for TextViewInstance {
fn get_title(&self) -> &str {
self.base_view.title.as_str()
}
fn get_priority(&self) -> usize {
self.base_view.priority
}
fn get_view_type(&self) -> &str {
"text_view"
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
impl<T: ?Sized> Debug for PhlowTextView<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PhlowTextView").finish()
}
}
impl<T: 'static> PhlowView for PhlowTextView<T> {
fn get_title(&self) -> &str {
self.base_view.title.as_str()
}
fn get_priority(&self) -> usize {
self.base_view.priority
}
fn get_view_type(&self) -> &str {
Self::view_type()
}
fn get_defining_method(&self) -> Option<&DefiningMethod> {
self.base_view.defining_method.as_ref()
}
fn create_instance(&self, object: ObjectRef<'_>) -> Box<dyn ViewInstance> {
let object = unsafe { object.cast::<T>() };
Box::new(TextViewInstance {
base_view: self.base_view.clone(),
text: self.compute_text(object).into_owned(),
})
}
fn view_type() -> &'static str
where
Self: Sized,
{
"text_view"
}
}