use cssparser::*; use crate::traits::{Parse, ToCss}; use crate::values::color::CssColor; use crate::macros::{enum_property, shorthand_property}; use crate::printer::Printer; use smallvec::SmallVec; // https://www.w3.org/TR/2021/WD-css-ui-4-20210316/#resize enum_property!(Resize, None, Both, Horizontal, Vertical, Block, Inline ); /// https://www.w3.org/TR/2021/WD-css-ui-4-20210316/#cursor #[derive(Debug, Clone, PartialEq)] pub struct CursorImage { pub url: String, pub hotspot: Option<(f32, f32)> } impl Parse for CursorImage { fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { let url = input.expect_url()?.as_ref().to_owned(); let hotspot = if let Ok(x) = input.try_parse(f32::parse) { let y = f32::parse(input)?; Some((x, y)) } else { None }; Ok(CursorImage { url, hotspot }) } } impl ToCss for CursorImage { fn to_css(&self, dest: &mut Printer) -> std::fmt::Result where W: std::fmt::Write { { use cssparser::ToCss; Token::UnquotedUrl(CowRcStr::from(self.url.as_ref())).to_css(dest)?; } if let Some((x, y)) = self.hotspot { dest.write_char(' ')?; x.to_css(dest)?; dest.write_char(' ')?; y.to_css(dest)?; } Ok(()) } } enum_property!(CursorKeyword, ("auto", Auto), ("default", Default), ("none", None), ("context-menu", ContextMenu), ("help", Help), ("pointer", Pointer), ("progress", Progress), ("wait", Wait), ("cell", Cell), ("crosshair", Crosshair), ("text", Text), ("vertical-text", VerticalText), ("alias", Alias), ("copy", Copy), ("move", Move), ("no-drop", NoDrop), ("not-allowed", NotAllowed), ("grab", Grab), ("grabbing", Grabbing), ("e-resize", EResize), ("n-resize", NResize), ("ne-resize", NeResize), ("nw-resize", NwResize), ("s-resize", SResize), ("se-resize", SeResize), ("sw-resize", SwResize), ("w-resize", WResize), ("ew-resize", EwResize), ("ns-resize", NsResize), ("nesw-resize", NeswResize), ("nwse-resize", NwseResize), ("col-resize", ColResize), ("row-resize", RowResize), ("all-scroll", AllScroll), ("zoom-in", ZoomIn), ("zoom-out", ZoomOut) ); /// https://www.w3.org/TR/2021/WD-css-ui-4-20210316/#cursor #[derive(Debug, Clone, PartialEq)] pub struct Cursor { pub images: SmallVec<[CursorImage; 1]>, pub keyword: CursorKeyword } impl Parse for Cursor { fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { let mut images = SmallVec::new(); loop { match input.try_parse(CursorImage::parse) { Ok(image) => images.push(image), Err(_) => break, } input.expect_comma()?; } Ok(Cursor { images, keyword: CursorKeyword::parse(input)? }) } } impl ToCss for Cursor { fn to_css(&self, dest: &mut Printer) -> std::fmt::Result where W: std::fmt::Write { for image in &self.images { image.to_css(dest)?; dest.delim(',', false)?; } self.keyword.to_css(dest) } } /// https://www.w3.org/TR/2021/WD-css-ui-4-20210316/#caret-color #[derive(Debug, Clone, PartialEq)] pub enum ColorOrAuto { Auto, Color(CssColor) } impl Default for ColorOrAuto { fn default() -> ColorOrAuto { ColorOrAuto::Auto } } impl Parse for ColorOrAuto { fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { if input.try_parse(|input| input.expect_ident_matching("auto")).is_ok() { return Ok(ColorOrAuto::Auto) } let color = CssColor::parse(input)?; Ok(ColorOrAuto::Color(color)) } } impl ToCss for ColorOrAuto { fn to_css(&self, dest: &mut Printer) -> std::fmt::Result where W: std::fmt::Write { match self { ColorOrAuto::Auto => dest.write_str("auto"), ColorOrAuto::Color(color) => color.to_css(dest) } } } // https://www.w3.org/TR/2021/WD-css-ui-4-20210316/#caret-shape enum_property!(CaretShape, Auto, Bar, Block, Underscore ); impl Default for CaretShape { fn default() -> CaretShape { CaretShape::Auto } } // https://www.w3.org/TR/2021/WD-css-ui-4-20210316/#caret shorthand_property!(Caret { color: ColorOrAuto, shape: CaretShape, }); // https://www.w3.org/TR/2021/WD-css-ui-4-20210316/#content-selection enum_property!(UserSelect, Auto, Text, None, Contain, All ); /// https://www.w3.org/TR/2021/WD-css-ui-4-20210316/#appearance-switching #[derive(Debug, Clone, PartialEq)] pub enum Appearance { None, Auto, Textfield, MenulistButton, Button, Checkbox, Listbox, Menulist, Meter, ProgressBar, PushButton, Radio, Searchfield, SliderHorizontal, SquareButton, Textarea, NonStandard(String) } impl Parse for Appearance { fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { let ident = input.expect_ident()?; match_ignore_ascii_case! { &*ident, "none" => Ok(Appearance::None), "auto" => Ok(Appearance::Auto), "textfield" => Ok(Appearance::Textfield), "menulist-button" => Ok(Appearance::MenulistButton), "button" => Ok(Appearance::Button), "checkbox" => Ok(Appearance::Checkbox), "listbox" => Ok(Appearance::Listbox), "menulist" => Ok(Appearance::Menulist), "meter" => Ok(Appearance::Meter), "progress-bar" => Ok(Appearance::ProgressBar), "push-button" => Ok(Appearance::PushButton), "radio" => Ok(Appearance::Radio), "searchfield" => Ok(Appearance::Searchfield), "slider-horizontal" => Ok(Appearance::SliderHorizontal), "square-button" => Ok(Appearance::SquareButton), "textarea" => Ok(Appearance::Textarea), _ => Ok(Appearance::NonStandard(ident.as_ref().to_owned())) } } } impl ToCss for Appearance { fn to_css(&self, dest: &mut Printer) -> std::fmt::Result where W: std::fmt::Write { match self { Appearance::None => dest.write_str("none"), Appearance::Auto => dest.write_str("auto"), Appearance::Textfield => dest.write_str("textfield"), Appearance::MenulistButton => dest.write_str("menulist-button"), Appearance::Button => dest.write_str("button"), Appearance::Checkbox => dest.write_str("checkbox"), Appearance::Listbox => dest.write_str("listbox"), Appearance::Menulist => dest.write_str("menulist"), Appearance::Meter => dest.write_str("meter"), Appearance::ProgressBar => dest.write_str("progress-bar"), Appearance::PushButton => dest.write_str("push-button"), Appearance::Radio => dest.write_str("radio"), Appearance::Searchfield => dest.write_str("searchfield"), Appearance::SliderHorizontal => dest.write_str("slider-horizontal"), Appearance::SquareButton => dest.write_str("square-button"), Appearance::Textarea => dest.write_str("textarea"), Appearance::NonStandard(s) => dest.write_str(&s) } } }