|
| 1 | +use proc_macro2::TokenStream; |
| 2 | +use quote::{quote, ToTokens}; |
| 3 | +use efx_attrnames::AttrNames; |
| 4 | +use efx_core::Element; |
| 5 | +use crate::tags::{Tag, TagAttributes}; |
| 6 | +use crate::utils::attr::*; |
| 7 | +use crate::utils::render::render_children_stmt; |
| 8 | + |
| 9 | +pub struct BottomPanel { |
| 10 | + attributes: Attributes, |
| 11 | + element: Element, |
| 12 | +} |
| 13 | + |
| 14 | +impl Tag for BottomPanel { |
| 15 | + fn from_element(el: &Element) -> Result<Self, TokenStream> |
| 16 | + where |
| 17 | + Self: Sized |
| 18 | + { |
| 19 | + Ok(Self { attributes: Attributes::new(el)?, element: el.clone() }) |
| 20 | + } |
| 21 | + |
| 22 | + fn content<UI: ToTokens>(&self, _ui: &UI) -> TokenStream { |
| 23 | + let mut ts = TokenStream::new(); |
| 24 | + |
| 25 | + ts.extend(match self.attributes.frame { |
| 26 | + Some(false) => quote!( let mut __efx_frame = egui::Frame::none(); ), |
| 27 | + _ => quote!( let mut __efx_frame = egui::Frame::default(); ), |
| 28 | + }); |
| 29 | + |
| 30 | + if let Some(fill) = &self.attributes.fill { |
| 31 | + ts.extend(quote!( __efx_frame = __efx_frame.fill(#fill); )); |
| 32 | + } |
| 33 | + if let Some(im) = self.attributes.padding_ts() { |
| 34 | + ts.extend(quote!( __efx_frame = __efx_frame.inner_margin(#im); )); |
| 35 | + } |
| 36 | + if let Some(om) = self.attributes.margin_ts() { |
| 37 | + ts.extend(quote!( __efx_frame = __efx_frame.outer_margin(#om); )); |
| 38 | + } |
| 39 | + if let Some(st) = stroke_tokens(self.attributes.stroke_width, self.attributes.stroke_color.clone()) { |
| 40 | + ts.extend(quote!( __efx_frame = __efx_frame.stroke(#st); )); |
| 41 | + } |
| 42 | + |
| 43 | + ts |
| 44 | + } |
| 45 | + |
| 46 | + fn render<UI: ToTokens>(&self, ui: &UI) -> TokenStream { |
| 47 | + let id = match &self.attributes.id { |
| 48 | + Some(s) if !s.is_empty() => s, |
| 49 | + _ => { |
| 50 | + let msg = "efx: <BottomPanel> requires non-empty `id` attribute"; |
| 51 | + return quote! { compile_error!(#msg); }; |
| 52 | + } |
| 53 | + }; |
| 54 | + |
| 55 | + let children = render_children_stmt("e!(ui), &self.element.children); |
| 56 | + let frame_ts = self.content(ui); |
| 57 | + |
| 58 | + let mut panel_ts = quote!( let mut __efx_panel = egui::TopBottomPanel::bottom(#id).frame(__efx_frame); ); |
| 59 | + if let Some(b) = self.attributes.resizable { |
| 60 | + panel_ts.extend(quote!( __efx_panel = __efx_panel.resizable(#b); )); |
| 61 | + } |
| 62 | + if let Some(v) = self.attributes.default_height { |
| 63 | + panel_ts.extend(quote!( __efx_panel = __efx_panel.default_height(#v as f32); )); |
| 64 | + } |
| 65 | + if let Some(v) = self.attributes.min_height { |
| 66 | + panel_ts.extend(quote!( __efx_panel = __efx_panel.min_height(#v as f32); )); |
| 67 | + } |
| 68 | + if let Some(v) = self.attributes.max_height { |
| 69 | + panel_ts.extend(quote!( __efx_panel = __efx_panel.max_height(#v as f32); )); |
| 70 | + } |
| 71 | + |
| 72 | + quote! {{ |
| 73 | + #frame_ts |
| 74 | + #panel_ts |
| 75 | + __efx_panel.show(&#ui.ctx(), |ui| { #children }); |
| 76 | + }} |
| 77 | + } |
| 78 | +} |
| 79 | + |
| 80 | +#[derive(Clone, Debug, AttrNames)] |
| 81 | +struct Attributes { |
| 82 | + id: Option<String>, |
| 83 | + |
| 84 | + frame: Option<bool>, |
| 85 | + fill: Option<TokenStream>, |
| 86 | + #[attr(name = "stroke-width")] |
| 87 | + stroke_width: Option<f32>, |
| 88 | + #[attr(name = "stroke-color")] |
| 89 | + stroke_color: Option<TokenStream>, |
| 90 | + |
| 91 | + #[attr(name = "default-height")] |
| 92 | + default_height: Option<f32>, |
| 93 | + #[attr(name = "min-height")] |
| 94 | + min_height: Option<f32>, |
| 95 | + #[attr(name = "max-height")] |
| 96 | + max_height: Option<f32>, |
| 97 | + resizable: Option<bool>, |
| 98 | + |
| 99 | + padding: Option<f32>, |
| 100 | + #[attr(name = "padding-left")] |
| 101 | + padding_l: Option<f32>, |
| 102 | + #[attr(name = "padding-right")] |
| 103 | + padding_r: Option<f32>, |
| 104 | + #[attr(name = "padding-top")] |
| 105 | + padding_t: Option<f32>, |
| 106 | + #[attr(name = "padding-bottom")] |
| 107 | + padding_b: Option<f32>, |
| 108 | + |
| 109 | + margin: Option<f32>, |
| 110 | + #[attr(name = "margin-left")] |
| 111 | + margin_l: Option<f32>, |
| 112 | + #[attr(name = "margin-right")] |
| 113 | + margin_r: Option<f32>, |
| 114 | + #[attr(name = "margin-top")] |
| 115 | + margin_t: Option<f32>, |
| 116 | + #[attr(name = "margin-bottom")] |
| 117 | + margin_b: Option<f32>, |
| 118 | +} |
| 119 | + |
| 120 | +impl Attributes { |
| 121 | + fn padding_ts(&self) -> Option<TokenStream> { |
| 122 | + margin_tokens(self.padding, self.padding_l, self.padding_r, self.padding_t, self.padding_b) |
| 123 | + } |
| 124 | + fn margin_ts(&self) -> Option<TokenStream> { |
| 125 | + margin_tokens(self.margin, self.margin_l, self.margin_r, self.margin_t, self.margin_b) |
| 126 | + } |
| 127 | +} |
| 128 | + |
| 129 | +impl TagAttributes for Attributes { |
| 130 | + fn new(el: &Element) -> Result<Self, TokenStream> { |
| 131 | + let map = attr_map(el, Attributes::ATTR_NAMES, "BottomPanel")?; |
| 132 | + Ok(Attributes { |
| 133 | + id: map.get("id").map(|s| (*s).to_string()), |
| 134 | + frame: bool_opt(&map, "frame")?, |
| 135 | + fill: color_tokens_opt(&map, "fill")?, |
| 136 | + stroke_width: f32_opt(&map, "stroke-width")?, |
| 137 | + stroke_color: color_tokens_opt(&map, "stroke-color")?, |
| 138 | + default_height: f32_opt(&map, "default-height")?, |
| 139 | + min_height: f32_opt(&map, "min-height")?, |
| 140 | + max_height: f32_opt(&map, "max-height")?, |
| 141 | + resizable: bool_opt(&map, "resizable")?, |
| 142 | + padding: f32_opt(&map, "padding")?, |
| 143 | + padding_l: f32_opt(&map, "padding-left")?, |
| 144 | + padding_r: f32_opt(&map, "padding-right")?, |
| 145 | + padding_t: f32_opt(&map, "padding-top")?, |
| 146 | + padding_b: f32_opt(&map, "padding-bottom")?, |
| 147 | + margin: f32_opt(&map, "margin")?, |
| 148 | + margin_l: f32_opt(&map, "margin-left")?, |
| 149 | + margin_r: f32_opt(&map, "margin-right")?, |
| 150 | + margin_t: f32_opt(&map, "margin-top")?, |
| 151 | + margin_b: f32_opt(&map, "margin-bottom")?, |
| 152 | + }) |
| 153 | + } |
| 154 | +} |
0 commit comments