use crate::error::Result;
use windows::Win32::Foundation::HWND;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ElementTheme {
#[default]
Default,
Light,
Dark,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum HorizontalAlignment {
Left,
Center,
Right,
#[default]
Stretch,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum VerticalAlignment {
Top,
Center,
Bottom,
#[default]
Stretch,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Visibility {
#[default]
Visible,
Collapsed,
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct Thickness {
pub left: f64,
pub top: f64,
pub right: f64,
pub bottom: f64,
}
impl Thickness {
pub const fn uniform(value: f64) -> Self {
Self {
left: value,
top: value,
right: value,
bottom: value,
}
}
pub const fn symmetric(horizontal: f64, vertical: f64) -> Self {
Self {
left: horizontal,
top: vertical,
right: horizontal,
bottom: vertical,
}
}
pub const fn new(left: f64, top: f64, right: f64, bottom: f64) -> Self {
Self {
left,
top,
right,
bottom,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct CornerRadius {
pub top_left: f64,
pub top_right: f64,
pub bottom_right: f64,
pub bottom_left: f64,
}
impl CornerRadius {
pub const fn uniform(value: f64) -> Self {
Self {
top_left: value,
top_right: value,
bottom_right: value,
bottom_left: value,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct XamlColor {
pub a: u8,
pub r: u8,
pub g: u8,
pub b: u8,
}
impl XamlColor {
pub const fn argb(a: u8, r: u8, g: u8, b: u8) -> Self {
Self { a, r, g, b }
}
pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
Self { a: 255, r, g, b }
}
pub const fn from_argb_hex(hex: u32) -> Self {
Self {
a: ((hex >> 24) & 0xFF) as u8,
r: ((hex >> 16) & 0xFF) as u8,
g: ((hex >> 8) & 0xFF) as u8,
b: (hex & 0xFF) as u8,
}
}
pub const fn from_rgb_hex(hex: u32) -> Self {
Self {
a: 255,
r: ((hex >> 16) & 0xFF) as u8,
g: ((hex >> 8) & 0xFF) as u8,
b: (hex & 0xFF) as u8,
}
}
pub const TRANSPARENT: Self = Self::argb(0, 0, 0, 0);
pub const BLACK: Self = Self::rgb(0, 0, 0);
pub const WHITE: Self = Self::rgb(255, 255, 255);
pub const RED: Self = Self::rgb(255, 0, 0);
pub const GREEN: Self = Self::rgb(0, 128, 0);
pub const BLUE: Self = Self::rgb(0, 0, 255);
pub const GRAY: Self = Self::rgb(128, 128, 128);
pub const LIGHT_GRAY: Self = Self::rgb(211, 211, 211);
pub const DARK_GRAY: Self = Self::rgb(169, 169, 169);
}
#[derive(Debug, Clone, PartialEq)]
pub enum GridLength {
Auto,
Pixel(f64),
Star(f64),
}
impl Default for GridLength {
fn default() -> Self {
GridLength::Star(1.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[repr(u16)]
pub enum FontWeight {
Thin = 100,
ExtraLight = 200,
Light = 300,
SemiLight = 350,
#[default]
Normal = 400,
Medium = 500,
SemiBold = 600,
Bold = 700,
ExtraBold = 800,
Black = 900,
ExtraBlack = 950,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum FontStyle {
#[default]
Normal,
Oblique,
Italic,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum TextWrapping {
#[default]
NoWrap,
Wrap,
WrapWholeWords,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum TextTrimming {
#[default]
None,
CharacterEllipsis,
WordEllipsis,
Clip,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Orientation {
#[default]
Horizontal,
Vertical,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ScrollBarVisibility {
Disabled,
#[default]
Auto,
Visible,
Hidden,
}
pub struct XamlHost {
hwnd: HWND,
}
impl XamlHost {
pub fn new(hwnd: HWND) -> Result<Self> {
Ok(Self { hwnd })
}
pub fn hwnd(&self) -> HWND {
self.hwnd
}
pub fn set_content<T>(&self, _content: T) -> Result<()> {
Ok(())
}
pub fn focus(&self) -> Result<()> {
Ok(())
}
}
pub struct UiBuilder {
pub theme: ElementTheme,
pub margin: Thickness,
pub padding: Thickness,
}
impl UiBuilder {
pub fn new() -> Self {
Self {
theme: ElementTheme::Default,
margin: Thickness::default(),
padding: Thickness::default(),
}
}
pub fn theme(mut self, theme: ElementTheme) -> Self {
self.theme = theme;
self
}
pub fn margin(mut self, margin: Thickness) -> Self {
self.margin = margin;
self
}
pub fn padding(mut self, padding: Thickness) -> Self {
self.padding = padding;
self
}
}
impl Default for UiBuilder {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_thickness() {
let t = Thickness::uniform(10.0);
assert_eq!(t.left, 10.0);
assert_eq!(t.right, 10.0);
let t2 = Thickness::symmetric(5.0, 10.0);
assert_eq!(t2.left, 5.0);
assert_eq!(t2.top, 10.0);
}
#[test]
fn test_corner_radius() {
let r = CornerRadius::uniform(8.0);
assert_eq!(r.top_left, 8.0);
assert_eq!(r.bottom_right, 8.0);
}
#[test]
fn test_xaml_color() {
let c = XamlColor::rgb(255, 128, 64);
assert_eq!(c.a, 255);
assert_eq!(c.r, 255);
assert_eq!(c.g, 128);
assert_eq!(c.b, 64);
let c2 = XamlColor::from_rgb_hex(0xFF8040);
assert_eq!(c2.r, 255);
assert_eq!(c2.g, 128);
assert_eq!(c2.b, 64);
}
#[test]
fn test_grid_length() {
let auto = GridLength::Auto;
let pixel = GridLength::Pixel(100.0);
let star = GridLength::Star(2.0);
assert!(matches!(auto, GridLength::Auto));
assert!(matches!(pixel, GridLength::Pixel(100.0)));
assert!(matches!(star, GridLength::Star(2.0)));
}
#[test]
fn test_font_weight() {
assert_eq!(FontWeight::Normal as u16, 400);
assert_eq!(FontWeight::Bold as u16, 700);
}
#[test]
fn test_ui_builder() {
let ui = UiBuilder::new()
.theme(ElementTheme::Dark)
.margin(Thickness::uniform(16.0))
.padding(Thickness::symmetric(8.0, 4.0));
assert_eq!(ui.theme, ElementTheme::Dark);
assert_eq!(ui.margin.left, 16.0);
assert_eq!(ui.padding.left, 8.0);
assert_eq!(ui.padding.top, 4.0);
}
}