use std::any::Any;
use std::fmt::{Debug, Display, Formatter};
use std::marker::PhantomData;
use crate::{PhlowObject, PhlowView, PhlowViewMethod, TypedPhlowObject, TypedPhlowObjectMut};
#[allow(unused)]
pub struct PhlowBitmapView<T> {
object: PhlowObject,
defining_method: PhlowViewMethod,
title: String,
priority: usize,
bitmap_computation: Box<dyn Fn(&PhlowObject) -> PhlowBitmap>,
phantom_data: PhantomData<T>,
}
impl<T: 'static> PhlowBitmapView<T> {
pub fn new(object: PhlowObject, defining_method: PhlowViewMethod) -> Self {
Self {
object,
defining_method,
title: "".to_string(),
priority: 10,
bitmap_computation: Box::new(|_object| PhlowBitmap::default()),
phantom_data: Default::default(),
}
}
pub fn title(mut self, title: impl Into<String>) -> Self {
self.title = title.into();
self
}
pub fn priority(mut self, priority: usize) -> Self {
self.priority = priority;
self
}
pub fn bitmap(
mut self,
bitmap_block: impl Fn(TypedPhlowObject<T>) -> PhlowBitmap + 'static,
) -> Self {
self.bitmap_computation = Box::new(move |each_object| match each_object.value_ref::<T>() {
Some(each_reference) => {
bitmap_block(TypedPhlowObject::new(each_object, &each_reference))
}
None => PhlowBitmap::default(),
});
self
}
pub fn bitmap_mut(
mut self,
bitmap_block: impl Fn(TypedPhlowObjectMut<T>) -> PhlowBitmap + 'static,
) -> Self {
self.bitmap_computation = Box::new(move |each_object| match each_object.value_mut::<T>() {
Some(mut each_reference) => {
bitmap_block(TypedPhlowObjectMut::new(each_object, &mut each_reference))
}
None => PhlowBitmap::default(),
});
self
}
pub fn compute_bitmap(&self) -> PhlowBitmap {
(self.bitmap_computation)(&self.object)
}
}
#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "view-specification", derive(serde::Serialize))]
pub struct PhlowBitmap {
pixels: Vec<u8>,
width: i32,
height: i32,
stride: i32,
format: PixelFormat,
}
impl PhlowBitmap {
pub fn new(
pixels: impl ToOwned<Owned = Vec<u8>>,
width: i32,
height: i32,
stride: i32,
format: PixelFormat,
) -> Self {
Self {
pixels: pixels.to_owned(),
width,
height,
stride,
format,
}
}
pub fn rgba8(pixels: impl ToOwned<Owned = Vec<u8>>, width: i32, height: i32) -> Self {
Self::new(pixels, width, height, width, PixelFormat::RGBA8888)
}
pub fn bgra8(pixels: impl ToOwned<Owned = Vec<u8>>, width: i32, height: i32) -> Self {
Self::new(pixels, width, height, width, PixelFormat::BGRA8888)
}
pub fn pixels(&self) -> &[u8] {
self.pixels.as_slice()
}
pub fn stride(&self) -> i32 {
self.stride
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "view-specification", derive(serde::Serialize))]
pub enum PixelFormat {
RGBA8888,
BGRA8888,
}
impl Default for PixelFormat {
fn default() -> Self {
Self::RGBA8888
}
}
impl<T: 'static> Debug for PhlowBitmapView<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PhlowBitmapView").finish()
}
}
impl<T: 'static> Display for PhlowBitmapView<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
writeln!(f, "{}", self.title.as_str())?;
writeln!(f, "{}", "---------------------",)?;
let bitmap = self.compute_bitmap();
writeln!(
f,
"Bitmap: {}x{}; format: {:?}",
bitmap.width, bitmap.height, bitmap.format
)?;
Ok(())
}
}
impl<T: 'static> PhlowView for PhlowBitmapView<T> {
fn get_title(&self) -> &str {
self.title.as_str()
}
fn get_priority(&self) -> usize {
self.priority
}
fn get_view_type(&self) -> &str {
Self::view_type()
}
fn get_defining_method(&self) -> &PhlowViewMethod {
&self.defining_method
}
fn view_type() -> &'static str
where
Self: Sized,
{
"bitmap_view"
}
fn object(&self) -> &PhlowObject {
&self.object
}
fn as_any(&self) -> &dyn Any {
self
}
fn to_any(self: Box<Self>) -> Box<dyn Any> {
self
}
#[cfg(feature = "view-specification")]
fn as_view_specification_builder(&self) -> &dyn crate::AsPhlowViewSpecification {
self
}
}
#[cfg(feature = "view-specification")]
mod specification {
use serde::Serialize;
use crate::{
AsPhlowViewSpecification, PhlowViewSpecification, PhlowViewSpecificationDataTransport,
PhlowViewSpecificationListingItem,
};
use base64::{
alphabet,
engine::{self, general_purpose},
Engine as _,
};
use super::*;
#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "view-specification", derive(serde::Serialize))]
pub struct PhlowBitmapSpecification {
pixels: String,
width: i32,
height: i32,
stride: i32,
format: PixelFormat,
}
impl PhlowBitmapSpecification {
pub fn new(bitmap: PhlowBitmap) -> Self {
Self {
pixels: (general_purpose::STANDARD.encode(bitmap.pixels())),
width: bitmap.width,
height: bitmap.height,
stride: bitmap.stride,
format: Default::default(),
}
}
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PhlowBitmapViewSpecification {
title: String,
priority: usize,
data_transport: PhlowViewSpecificationDataTransport,
bitmap: PhlowBitmapSpecification,
method_selector: String,
}
#[typetag::serialize(name = "GtPhlowBitmapViewSpecification")]
#[async_trait::async_trait]
impl PhlowViewSpecification for PhlowBitmapViewSpecification {
async fn retrieve_items(&self) -> Vec<Box<dyn PhlowViewSpecificationListingItem>> {
vec![]
}
async fn retrieve_sent_item(&self, item: &PhlowObject) -> Option<PhlowObject> {
Some(item.clone())
}
}
impl<T: 'static> AsPhlowViewSpecification for PhlowBitmapView<T> {
fn create_view_specification(&self) -> Option<Box<dyn PhlowViewSpecification>> {
Some(Box::new(PhlowBitmapViewSpecification {
title: self.get_title().to_string(),
priority: self.get_priority(),
data_transport: PhlowViewSpecificationDataTransport::Included,
bitmap: PhlowBitmapSpecification::new(self.compute_bitmap()),
method_selector: self.get_defining_method().full_method_name.clone(),
}))
}
}
}