use std::cell::Ref;
use cosmic_text::{Buffer, LayoutRun};
use taffy::TraversePartialTree;
use crate::geometry::{Point, Rect, Size};
use crate::style::{Color, Style};
use crate::text::TextNode;
use crate::tree::{Node, NodeId, NodeKind, Tree, icon_rect};
use crate::widgets::IconSource;
const DEFAULT_TEXT_COLOR: Color = Color::rgb(0, 0, 0);
pub struct WindowView<'w> {
tree: Ref<'w, Tree>,
}
impl<'w> WindowView<'w> {
pub(crate) fn new(tree: Ref<'w, Tree>) -> WindowView<'w> {
WindowView { tree }
}
pub fn size(&self) -> Size {
self.tree.size
}
pub fn root(&self) -> NodeView<'_> {
NodeView::new(&self.tree, self.tree.root)
.expect("invariant: the root node exists while the tree does")
}
}
#[derive(Clone, Copy)]
pub struct NodeView<'a> {
tree: &'a Tree,
id: NodeId,
node: &'a Node,
}
impl<'a> NodeView<'a> {
fn new(tree: &'a Tree, id: NodeId) -> Option<NodeView<'a>> {
let node = tree.node(id)?;
Some(NodeView { tree, id, node })
}
pub fn name(&self) -> &'static str {
self.node.name
}
pub fn path(&self) -> &'a str {
&self.node.path
}
pub fn rect(&self) -> Rect {
self.node.rect.unwrap_or_default()
}
pub fn bounds(&self) -> Rect {
self.node.bounds
}
pub fn style(&self) -> Style {
self.node.effective_style()
}
pub fn children(&self) -> impl Iterator<Item = NodeView<'a>> + 'a {
let tree = self.tree;
tree
.taffy
.child_ids(self.id)
.filter_map(move |id| NodeView::new(tree, id))
}
pub fn content(&self) -> Content<'a> {
match &self.node.kind {
NodeKind::Text(text) => Content::Text(TextView {
text,
color: self.inherited_color(),
}),
NodeKind::Icon(icon) => match &icon.source {
Some(source) => Content::Icon(IconView {
source,
rect: icon_rect(self.node.content, icon.size),
}),
None => Content::None,
},
_ => Content::None,
}
}
fn inherited_color(&self) -> Color {
let mut id = Some(self.id);
while let Some(current) = id {
if let Some(color) = self
.tree
.node(current)
.and_then(|node| node.effective_style().color)
{
return color;
}
id = self.tree.taffy.parent(current);
}
DEFAULT_TEXT_COLOR
}
}
pub enum Content<'a> {
None,
Text(TextView<'a>),
Icon(IconView<'a>),
}
pub struct TextView<'a> {
text: &'a TextNode,
color: Color,
}
impl<'a> TextView<'a> {
pub fn content(&self) -> &'a str {
&self.text.content
}
pub fn buffer(&self) -> &'a Buffer {
&self.text.buffer
}
pub fn runs(&self) -> impl Iterator<Item = LayoutRun<'a>> + 'a {
self.text.runs()
}
pub fn origin(&self) -> Point {
self.text.origin
}
pub fn color(&self) -> Color {
self.color
}
}
pub struct IconView<'a> {
pub source: &'a IconSource,
pub rect: Rect,
}