use densa_core::{Point, Rect, Size};
use densa_paragraph::TextSystem;
use crate::ui::State;
use crate::{Action, ActionKind, Clipboard, Cursor, Style, Theme, WidgetId};
#[derive(Debug)]
pub struct LayoutCx<'a> {
pub(crate) text: &'a mut TextSystem,
pub(crate) theme: &'a Theme,
pub(crate) scale: f32,
}
impl LayoutCx<'_> {
pub fn text_system(&mut self) -> &mut TextSystem {
self.text
}
pub fn theme(&self) -> &Theme {
self.theme
}
pub fn scale(&self) -> f32 {
self.scale
}
pub fn px(&self, logical: f32) -> f32 {
logical * self.scale
}
}
#[derive(Debug, Clone, Copy)]
pub struct PaintCx<'a> {
pub(crate) state: &'a State,
pub(crate) id: WidgetId,
}
impl PaintCx<'_> {
pub fn id(&self) -> WidgetId {
self.id
}
pub fn rect(&self) -> Rect {
self.state.nodes[self.id.slot()].rect
}
pub fn content_rect(&self) -> Rect {
self.state.nodes[self.id.slot()].content
}
pub fn scroll(&self) -> Point {
self.state.nodes[self.id.slot()].scroll
}
pub fn content_size(&self) -> Size {
self.state.nodes[self.id.slot()].content_size
}
pub fn is_hovered(&self) -> bool {
self.state.nodes[self.id.slot()].hovered
}
pub fn is_focused(&self) -> bool {
self.state.focus == Some(self.id)
}
pub fn is_pressed(&self) -> bool {
self.state.capture == Some(self.id)
}
pub fn is_hover_target(&self) -> bool {
self.state.hover == Some(self.id)
}
pub fn children(&self) -> &[WidgetId] {
&self.state.nodes[self.id.slot()].children
}
pub fn rect_of(&self, id: WidgetId) -> Option<Rect> {
self.state.node(id).map(|node| node.rect)
}
pub fn theme(&self) -> &Theme {
&self.state.theme
}
pub fn scale(&self) -> f32 {
self.state.scale
}
pub fn px(&self, logical: f32) -> f32 {
logical * self.state.scale
}
}
#[derive(Debug)]
pub struct EventCx<'a> {
pub(crate) state: &'a mut State,
pub(crate) id: WidgetId,
}
impl EventCx<'_> {
pub fn id(&self) -> WidgetId {
self.id
}
pub fn rect(&self) -> Rect {
self.state.nodes[self.id.slot()].rect
}
pub fn content_rect(&self) -> Rect {
self.state.nodes[self.id.slot()].content
}
pub fn scroll(&self) -> Point {
self.state.nodes[self.id.slot()].scroll
}
pub fn content_size(&self) -> Size {
self.state.nodes[self.id.slot()].content_size
}
pub fn is_hovered(&self) -> bool {
self.state.nodes[self.id.slot()].hovered
}
pub fn is_focused(&self) -> bool {
self.state.focus == Some(self.id)
}
pub fn is_pressed(&self) -> bool {
self.state.capture == Some(self.id)
}
pub fn theme(&self) -> &Theme {
&self.state.theme
}
pub fn scale(&self) -> f32 {
self.state.scale
}
pub fn px(&self, logical: f32) -> f32 {
logical * self.state.scale
}
pub fn text_system(&mut self) -> &mut TextSystem {
&mut self.state.text
}
pub fn request_paint(&mut self) {
self.state.needs_paint = true;
}
pub fn clipboard(&mut self) -> &mut dyn Clipboard {
self.state.clipboard.0.as_mut()
}
pub fn request_layout(&mut self) {
self.state.mark_dirty(self.id);
}
pub fn request_focus(&mut self) {
self.state.requested_focus = Some(Some(self.id));
}
pub fn release_focus(&mut self) {
if self.state.focus == Some(self.id) {
self.state.requested_focus = Some(None);
}
}
pub fn release_pointer(&mut self) {
if self.state.capture == Some(self.id) {
self.state.capture = None;
}
}
pub fn set_cursor(&mut self, cursor: Option<Cursor>) {
self.state.nodes[self.id.slot()].cursor = cursor;
}
pub fn set_ime_area(&mut self, area: Option<Rect>) {
self.state.ime_area = area.map(|area| (self.id, area));
}
pub fn emit(&mut self, kind: ActionKind) {
let source = self.id;
self.state.actions.push_back(Action { source, kind });
}
pub fn scroll_to(&mut self, offset: Point) -> Point {
self.state.scroll_to(self.id, offset)
}
pub fn children(&self) -> &[WidgetId] {
&self.state.nodes[self.id.slot()].children
}
pub fn rect_of(&self, id: WidgetId) -> Option<Rect> {
self.state.node(id).map(|node| node.rect)
}
pub fn style_of(&self, id: WidgetId) -> Option<&Style> {
self.state.node(id).map(|node| &node.style)
}
pub fn focus_within(&self, id: WidgetId) -> bool {
self.state
.focus
.is_some_and(|focus| self.state.is_within(focus, id))
}
pub fn set_style(&mut self, id: WidgetId, style: Style) -> bool {
self.state.is_within(id, self.id) && self.state.set_style(id, style)
}
}