add transforms
This commit is contained in:
parent
11e1bd975f
commit
ec10e5a89d
3 changed files with 390 additions and 0 deletions
|
@ -46,6 +46,9 @@ pub mod prelude {
|
||||||
TextDecoration, TextHyphens, TextOverflow, TextTransform, TextWhitespace, TextWordBreak,
|
TextDecoration, TextHyphens, TextOverflow, TextTransform, TextWhitespace, TextWordBreak,
|
||||||
TextWrap, UnderlineOffset, VerticalTextAlignment,
|
TextWrap, UnderlineOffset, VerticalTextAlignment,
|
||||||
};
|
};
|
||||||
|
pub use super::primitives::transform::{
|
||||||
|
RenderTransformCPU, RenderTransformGPU, Rotate, Scale, Skew, Transform, TransformOrigin,
|
||||||
|
};
|
||||||
pub use super::primitives::visibility::Visibility;
|
pub use super::primitives::visibility::Visibility;
|
||||||
pub use super::primitives::width::{MaxWidth, MinWidth, Width};
|
pub use super::primitives::width::{MaxWidth, MinWidth, Width};
|
||||||
pub use super::primitives::zindex::ZIndex;
|
pub use super::primitives::zindex::ZIndex;
|
||||||
|
|
|
@ -21,6 +21,7 @@ pub mod shadow;
|
||||||
pub mod sized;
|
pub mod sized;
|
||||||
pub mod space;
|
pub mod space;
|
||||||
pub mod text;
|
pub mod text;
|
||||||
|
pub mod transform;
|
||||||
pub mod visibility;
|
pub mod visibility;
|
||||||
pub mod width;
|
pub mod width;
|
||||||
pub mod zindex;
|
pub mod zindex;
|
||||||
|
@ -104,6 +105,7 @@ pub enum Side {
|
||||||
TopRight,
|
TopRight,
|
||||||
BottomRight,
|
BottomRight,
|
||||||
BottomLeft,
|
BottomLeft,
|
||||||
|
Center,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Side {
|
impl Side {
|
||||||
|
@ -124,6 +126,7 @@ impl Side {
|
||||||
Self::TopRight => "tr",
|
Self::TopRight => "tr",
|
||||||
Self::BottomRight => "br",
|
Self::BottomRight => "br",
|
||||||
Self::BottomLeft => "bl",
|
Self::BottomLeft => "bl",
|
||||||
|
Self::Center => "center",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
384
src/ui/primitives/transform.rs
Normal file
384
src/ui/primitives/transform.rs
Normal file
|
@ -0,0 +1,384 @@
|
||||||
|
use crate::ui::UIWidget;
|
||||||
|
use maud::{Markup, Render, html};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
Side,
|
||||||
|
flex::Either,
|
||||||
|
space::{Fraction, ScreenValue},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn Scale<T: UIWidget + 'static>(size: f64, inner: T) -> ScaleWidget {
|
||||||
|
ScaleWidget(Box::new(inner), size, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ScaleWidget(Box<dyn UIWidget>, f64, u8);
|
||||||
|
|
||||||
|
impl ScaleWidget {
|
||||||
|
pub fn x(mut self) -> Self {
|
||||||
|
self.2 = 1;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn y(mut self) -> Self {
|
||||||
|
self.2 = 2;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Render for ScaleWidget {
|
||||||
|
fn render(&self) -> Markup {
|
||||||
|
self.render_with_class("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UIWidget for ScaleWidget {
|
||||||
|
fn can_inherit(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_class(&self) -> Vec<String> {
|
||||||
|
match self.2 {
|
||||||
|
1 => vec![format!("scale-x-[{:.2}]", self.1)],
|
||||||
|
2 => vec![format!("scale-y-[{:.2}]", self.1)],
|
||||||
|
_ => vec![format!("scale-[{:.2}]", self.1)],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extended_class(&self) -> Vec<String> {
|
||||||
|
let mut c = self.base_class();
|
||||||
|
c.extend_from_slice(&self.0.extended_class());
|
||||||
|
c
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_with_class(&self, class: &str) -> Markup {
|
||||||
|
if self.0.as_ref().can_inherit() {
|
||||||
|
self.0
|
||||||
|
.as_ref()
|
||||||
|
.render_with_class(&format!("{} {class}", self.base_class().join(" ")))
|
||||||
|
} else {
|
||||||
|
html! {
|
||||||
|
div class=(format!("{} {class}", self.base_class().join(" "))) {
|
||||||
|
(self.0.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn Rotate<T: UIWidget + 'static>(deg: u32, inner: T) -> RotateWidget {
|
||||||
|
RotateWidget(Box::new(inner), deg)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RotateWidget(Box<dyn UIWidget>, u32);
|
||||||
|
|
||||||
|
impl Render for RotateWidget {
|
||||||
|
fn render(&self) -> Markup {
|
||||||
|
self.render_with_class("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UIWidget for RotateWidget {
|
||||||
|
fn can_inherit(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_class(&self) -> Vec<String> {
|
||||||
|
vec![format!("rotate-[{:.2}deg]", self.1)]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extended_class(&self) -> Vec<String> {
|
||||||
|
let mut c = self.base_class();
|
||||||
|
c.extend_from_slice(&self.0.extended_class());
|
||||||
|
c
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_with_class(&self, class: &str) -> Markup {
|
||||||
|
if self.0.as_ref().can_inherit() {
|
||||||
|
self.0
|
||||||
|
.as_ref()
|
||||||
|
.render_with_class(&format!("{} {class}", self.base_class().join(" ")))
|
||||||
|
} else {
|
||||||
|
html! {
|
||||||
|
div class=(format!("{} {class}", self.base_class().join(" "))) {
|
||||||
|
(self.0.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn RenderTransformCPU<T: UIWidget + 'static>(inner: T) -> HardwareAccelerationWidget {
|
||||||
|
HardwareAccelerationWidget(Box::new(inner), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn RenderTransformGPU<T: UIWidget + 'static>(inner: T) -> HardwareAccelerationWidget {
|
||||||
|
HardwareAccelerationWidget(Box::new(inner), 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HardwareAccelerationWidget(Box<dyn UIWidget>, u8);
|
||||||
|
|
||||||
|
impl Render for HardwareAccelerationWidget {
|
||||||
|
fn render(&self) -> Markup {
|
||||||
|
self.render_with_class("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UIWidget for HardwareAccelerationWidget {
|
||||||
|
fn can_inherit(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_class(&self) -> Vec<String> {
|
||||||
|
match self.1 {
|
||||||
|
1 => vec!["transform-gpu".to_string()],
|
||||||
|
_ => vec!["transform-cpu".to_string()],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extended_class(&self) -> Vec<String> {
|
||||||
|
let mut c = self.base_class();
|
||||||
|
c.extend_from_slice(&self.0.extended_class());
|
||||||
|
c
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_with_class(&self, class: &str) -> Markup {
|
||||||
|
if self.0.as_ref().can_inherit() {
|
||||||
|
self.0
|
||||||
|
.as_ref()
|
||||||
|
.render_with_class(&format!("{} {class}", self.base_class().join(" ")))
|
||||||
|
} else {
|
||||||
|
html! {
|
||||||
|
div class=(format!("{} {class}", self.base_class().join(" "))) {
|
||||||
|
(self.0.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn Transform<
|
||||||
|
T: UIWidget + 'static,
|
||||||
|
X: Into<Either<ScreenValue, Fraction>>,
|
||||||
|
Y: Into<Either<ScreenValue, Fraction>>,
|
||||||
|
>(
|
||||||
|
x: Option<X>,
|
||||||
|
y: Option<Y>,
|
||||||
|
inner: T,
|
||||||
|
) -> TransformWidget {
|
||||||
|
TransformWidget {
|
||||||
|
inner: Box::new(inner),
|
||||||
|
x: x.map(|x| x.into()),
|
||||||
|
y: y.map(|y| y.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TransformWidget {
|
||||||
|
inner: Box<dyn UIWidget>,
|
||||||
|
x: Option<Either<ScreenValue, Fraction>>,
|
||||||
|
y: Option<Either<ScreenValue, Fraction>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Render for TransformWidget {
|
||||||
|
fn render(&self) -> Markup {
|
||||||
|
self.render_with_class("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UIWidget for TransformWidget {
|
||||||
|
fn can_inherit(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_class(&self) -> Vec<String> {
|
||||||
|
let mut ret = Vec::new();
|
||||||
|
|
||||||
|
if let Some(x) = &self.x {
|
||||||
|
ret.push(format!(
|
||||||
|
"translate-x-{}",
|
||||||
|
x.map(|x| x.to_value().to_string(), |x| x.to_value().to_string())
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(y) = &self.y {
|
||||||
|
ret.push(format!(
|
||||||
|
"translate-y-{}",
|
||||||
|
y.map(|y| y.to_value().to_string(), |y| y.to_value().to_string())
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extended_class(&self) -> Vec<String> {
|
||||||
|
let mut c = self.base_class();
|
||||||
|
c.extend_from_slice(&self.inner.extended_class());
|
||||||
|
c
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_with_class(&self, class: &str) -> Markup {
|
||||||
|
if self.inner.as_ref().can_inherit() {
|
||||||
|
self.inner
|
||||||
|
.as_ref()
|
||||||
|
.render_with_class(&format!("{} {class}", self.base_class().join(" ")))
|
||||||
|
} else {
|
||||||
|
html! {
|
||||||
|
div class=(format!("{} {class}", self.base_class().join(" "))) {
|
||||||
|
(self.inner.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum SkewValue {
|
||||||
|
_0,
|
||||||
|
_1,
|
||||||
|
_2,
|
||||||
|
_3,
|
||||||
|
_6,
|
||||||
|
_12,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SkewValue {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
SkewValue::_0 => "0",
|
||||||
|
SkewValue::_1 => "1",
|
||||||
|
SkewValue::_2 => "2",
|
||||||
|
SkewValue::_3 => "3",
|
||||||
|
SkewValue::_6 => "6",
|
||||||
|
SkewValue::_12 => "12",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn Skew<T: UIWidget + 'static>(
|
||||||
|
x: Option<SkewValue>,
|
||||||
|
y: Option<SkewValue>,
|
||||||
|
inner: T,
|
||||||
|
) -> SkewWidget {
|
||||||
|
SkewWidget {
|
||||||
|
inner: Box::new(inner),
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SkewWidget {
|
||||||
|
inner: Box<dyn UIWidget>,
|
||||||
|
x: Option<SkewValue>,
|
||||||
|
y: Option<SkewValue>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Render for SkewWidget {
|
||||||
|
fn render(&self) -> Markup {
|
||||||
|
self.render_with_class("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UIWidget for SkewWidget {
|
||||||
|
fn can_inherit(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_class(&self) -> Vec<String> {
|
||||||
|
let mut ret = Vec::new();
|
||||||
|
|
||||||
|
if let Some(x) = &self.x {
|
||||||
|
ret.push(format!("skew-x-{}", x.to_value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(y) = &self.y {
|
||||||
|
ret.push(format!("skew-y-{}", y.to_value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extended_class(&self) -> Vec<String> {
|
||||||
|
let mut c = self.base_class();
|
||||||
|
c.extend_from_slice(&self.inner.extended_class());
|
||||||
|
c
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_with_class(&self, class: &str) -> Markup {
|
||||||
|
if self.inner.as_ref().can_inherit() {
|
||||||
|
self.inner
|
||||||
|
.as_ref()
|
||||||
|
.render_with_class(&format!("{} {class}", self.base_class().join(" ")))
|
||||||
|
} else {
|
||||||
|
html! {
|
||||||
|
div class=(format!("{} {class}", self.base_class().join(" "))) {
|
||||||
|
(self.inner.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn TransformOrigin<T: UIWidget + 'static>(origin: Side, inner: T) -> TransformOriginWidget {
|
||||||
|
TransformOriginWidget(Box::new(inner), origin)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TransformOriginWidget(Box<dyn UIWidget>, Side);
|
||||||
|
|
||||||
|
impl Render for TransformOriginWidget {
|
||||||
|
fn render(&self) -> Markup {
|
||||||
|
self.render_with_class("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UIWidget for TransformOriginWidget {
|
||||||
|
fn can_inherit(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_class(&self) -> Vec<String> {
|
||||||
|
let side = match self.1 {
|
||||||
|
Side::Start => "top",
|
||||||
|
Side::End => "bottom",
|
||||||
|
Side::Top => "top",
|
||||||
|
Side::Right => "right",
|
||||||
|
Side::Bottom => "bottom",
|
||||||
|
Side::Left => "left",
|
||||||
|
Side::StartStart => "top-left",
|
||||||
|
Side::StartEnd => "top-right",
|
||||||
|
Side::EndEnd => "bottom-right",
|
||||||
|
Side::EndStart => "bottom-left",
|
||||||
|
Side::TopLeft => "top-left",
|
||||||
|
Side::TopRight => "top-right",
|
||||||
|
Side::BottomRight => "bottom-right",
|
||||||
|
Side::BottomLeft => "bottom-left",
|
||||||
|
Side::Center => "center",
|
||||||
|
};
|
||||||
|
|
||||||
|
vec![format!("origin-{side}")]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extended_class(&self) -> Vec<String> {
|
||||||
|
let mut c = self.base_class();
|
||||||
|
c.extend_from_slice(&self.0.extended_class());
|
||||||
|
c
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_with_class(&self, class: &str) -> Markup {
|
||||||
|
if self.0.as_ref().can_inherit() {
|
||||||
|
self.0
|
||||||
|
.as_ref()
|
||||||
|
.render_with_class(&format!("{} {class}", self.base_class().join(" ")))
|
||||||
|
} else {
|
||||||
|
html! {
|
||||||
|
div class=(format!("{} {class}", self.base_class().join(" "))) {
|
||||||
|
(self.0.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue