use teksilo_canvas::{Canvas, Rect, SizeProposal};
use teksilo_core::accessibility::AccessNodeBuilder;
use teksilo_core::binding::BindingLevel;
use teksilo_core::build_context::BuildContext;
use teksilo_core::signal::Signal;
use teksilo_core::styles::{WebViewStyle, WebViewStyleConfig, WebViewVisualState};
use teksilo_core::widget::{LayoutContext, LayoutResponse, PaintContext, Widget, WidgetPlacement};
use teksilo_core::widget_id::WidgetId;
use teksilo_tokens::{BorderRole, CornerRadius};
const FOCUS_RING_WIDTH: f32 = 2.0;
#[derive(Debug, Default, Clone, Copy)]
pub struct RecipeWebViewStyle;
impl WebViewStyle for RecipeWebViewStyle {
fn make_body(&self, cfg: &WebViewStyleConfig, ctx: &mut BuildContext) -> WidgetId {
ctx.add(WebViewOverlay {
state: cfg.state.clone(),
focused: cfg.focused.clone(),
content: cfg.content,
})
}
}
#[derive(Debug)]
struct WebViewOverlay {
state: Signal<WebViewVisualState>,
focused: Signal<bool>,
content: WidgetId,
}
impl Widget for WebViewOverlay {
fn build(&mut self, ctx: &mut BuildContext) -> Vec<WidgetId> {
let self_id = ctx.self_id();
self.state
.bind_to(self_id, ctx.binding_registry(), BindingLevel::RepaintOnly);
self.focused
.bind_to(self_id, ctx.binding_registry(), BindingLevel::RepaintOnly);
vec![self.content]
}
fn layout_response(&self, proposal: SizeProposal, _ctx: &LayoutContext) -> LayoutResponse {
proposal.resolve(0.0, 0.0).into()
}
fn place_children(
&self,
bounds: Rect,
_proposal: SizeProposal,
children: &mut [WidgetPlacement],
_ctx: &LayoutContext,
) {
for child in children.iter_mut() {
child.origin = bounds.origin();
child.size = bounds.size();
}
}
fn paint(&self, bounds: Rect, canvas: &mut Canvas, ctx: &PaintContext) {
let role = self.state.get().surface_role();
let color = role.resolve(&ctx.theme.colors);
if color.a() > 0.0 {
canvas.fill_rounded_rect(bounds, CornerRadius::ZERO, color);
}
if self.focused.get() {
let w = FOCUS_RING_WIDTH;
let rect = Rect::new(
bounds.x + w * 0.5,
bounds.y + w * 0.5,
(bounds.width - w).max(0.0),
(bounds.height - w).max(0.0),
);
canvas.stroke_rect(rect, BorderRole::Focused.resolve(&ctx.theme.colors), w);
}
}
fn accessibility(&self, builder: &mut AccessNodeBuilder) {
builder.set_hidden();
}
fn children(&self) -> Vec<WidgetId> {
vec![self.content]
}
}