use crate::point::Point;
use crate::rect::Rect;
use crate::traits::*;
use num_traits::NumCast;
use std::fmt;
use std::hash::Hash;
use std::ops::Deref;
pub trait TextType: Eq + Hash + Clone + fmt::Debug {}
impl<T: Eq + Hash + Clone + fmt::Debug> TextType for T {}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Text<T, S = String> {
location: Point<T>,
text: S,
}
impl<T, S> fmt::Display for Text<T, S>
where
T: fmt::Display,
S: TextType + fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Text({}, {})", self.text, self.location)
}
}
impl<T, S> Deref for Text<T, S>
where
S: Deref<Target = String>,
{
type Target = String;
fn deref(&self) -> &Self::Target {
self.text.deref()
}
}
impl<T, S: TextType> Text<T, S> {
pub fn new(text: S, location: Point<T>) -> Self {
Text { location, text }
}
pub fn text(&self) -> &S {
&self.text
}
}
impl<T: Copy, S: TextType> Text<T, S> {
#[inline]
pub fn location(&self) -> Point<T> {
self.location
}
#[inline]
pub fn x(&self) -> T {
self.location.x
}
#[inline]
pub fn y(&self) -> T {
self.location.y
}
}
impl<T: Copy + PartialOrd, S> TryBoundingBox<T> for Text<T, S> {
fn try_bounding_box(&self) -> Option<Rect<T>> {
Some(Rect::new(self.location, self.location))
}
}
impl<T, Dst, S> TryCastCoord<T, Dst> for Text<T, S>
where
T: Copy + NumCast,
Dst: Copy + NumCast,
S: Clone,
{
type Output = Text<Dst, S>;
fn try_cast(&self) -> Option<Self::Output> {
self.location.try_cast().map(|loc| Text {
location: loc,
text: self.text.clone(),
})
}
}
impl<T, S> MapPointwise<T> for Text<T, S>
where
T: Copy,
S: Clone,
{
#[inline]
fn transform<F>(&self, transformation: F) -> Self
where
F: Fn(Point<T>) -> Point<T>,
{
Text {
location: transformation(self.location),
text: self.text.clone(),
}
}
}