use super::id::NodeId;
use super::overlay::ScrollbarZone;
use crate::callback::ScopeId;
use crate::style::{Rect, Theme};
#[cfg(feature = "big-text")]
use crate::widgets::internal::BigTextNode;
#[cfg(feature = "terminal")]
use crate::widgets::internal::TerminalNode;
#[cfg(feature = "image")]
use crate::widgets::Image;
use crate::widgets::document_view::node::DocumentViewNode;
#[cfg(feature = "image")]
use crate::widgets::internal::ImageNode;
use crate::widgets::internal::{
AnimatedNode, AsciiCanvasNode, CanvasNode, CenterPinNode, ChartNode, CheckboxNode,
ClassDiagramNode, DragSourceNode, DraggableTabBarNode, DropTargetNode, EffectScopeNode,
ErDiagramNode, FlowNode, FlowchartNode, FrameNode, GanttDiagramNode, GraphRenderNode, GridNode,
HeatmapNode, HexAreaNode, MouseRegionNode, PanViewNode, ProgressNode, ScrollViewNode,
SequenceDiagramNode, SliderNode, SparklineNode, SpinnerNode, SplitterNode, StackNode,
StateDiagramNode, StatusBarLayoutNode, TableNode, TabsNode, ZStackNode,
};
use crate::widgets::{
Animated, AsciiCanvas, Button, Chart, Checkbox, ClassDiagram, DragSource, DraggableTabBar,
DropTarget, EffectScope, ErDiagram, Flowchart, GanttDiagram, Graph, Heatmap, HexArea, Input,
MouseRegion, PanView, ProgressBar, SequenceDiagram, Slider, Sparkline, Spinner, Splitter,
StateDiagram, Table, Tabs, TextArea,
};
pub(crate) trait WidgetNode {
fn is_focusable(&self) -> bool {
false
}
fn in_tab_order(&self) -> bool {
self.is_focusable()
}
fn has_on_click(&self) -> bool {
false
}
fn has_on_mouse_move(&self) -> bool {
false
}
fn is_hoverable(&self) -> bool {
self.has_on_click()
}
fn is_hoverable_for_theme(&self, _theme: &Theme) -> bool {
self.is_hoverable()
}
fn hit_test_refinement(&self, _x: i16, _y: i16, _rect: Rect) -> Option<bool> {
None
}
fn hover_test_refinement(&self, x: i16, y: i16, rect: Rect) -> Option<bool> {
self.hit_test_refinement(x, y, rect)
}
fn scrollbar_zones(
&self,
_id: NodeId,
_rect: Rect,
_parent_border_x: Option<i16>,
_parent_border_y: Option<i16>,
) -> Vec<ScrollbarZone> {
Vec::new()
}
}
#[derive(Clone)]
pub(crate) struct GroupNode {
pub scope: ScopeId,
}
impl WidgetNode for GroupNode {}
macro_rules! node_kind_delegate_match {
($self:expr, $method:ident($($arg:expr),* $(,)?)) => {
match $self {
Self::Text(n) => n.$method($($arg),*),
Self::AsciiCanvas(n) => n.$method($($arg),*),
Self::Button(n) => n.$method($($arg),*),
Self::Input(n) => n.$method($($arg),*),
Self::HexArea(n) => n.$method($($arg),*),
Self::List(n) => n.$method($($arg),*),
Self::TextArea(n) => n.$method($($arg),*),
Self::Table(n) => n.$method($($arg),*),
Self::Tabs(n) => n.$method($($arg),*),
Self::DraggableTabBar(n) => n.$method($($arg),*),
Self::Divider(n) => n.$method($($arg),*),
Self::Spacer(n) => n.$method($($arg),*),
Self::Checkbox(n) => n.$method($($arg),*),
Self::ProgressBar(n) => n.$method($($arg),*),
Self::Slider(n) => n.$method($($arg),*),
Self::Spinner(n) => n.$method($($arg),*),
Self::Splitter(n) => n.$method($($arg),*),
Self::Heatmap(n) => n.$method($($arg),*),
Self::DocumentView(n) => n.$method($($arg),*),
Self::PanView(n) => n.$method($($arg),*),
Self::Flow(n) => n.$method($($arg),*),
Self::Canvas(n) => n.$method($($arg),*),
#[cfg(feature = "image")]
Self::Image(n) => n.$method($($arg),*),
Self::Sparkline(n) => n.$method($($arg),*),
Self::Chart(n) => n.$method($($arg),*),
Self::Graph(n) => n.$method($($arg),*),
Self::SequenceDiagram(n) => n.$method($($arg),*),
Self::Flowchart(n) => n.$method($($arg),*),
Self::ClassDiagram(n) => n.$method($($arg),*),
Self::StateDiagram(n) => n.$method($($arg),*),
Self::ErDiagram(n) => n.$method($($arg),*),
Self::GanttDiagram(n) => n.$method($($arg),*),
Self::StatusBarLayout(n) => n.$method($($arg),*),
#[cfg(feature = "terminal")]
Self::Terminal(n) => n.$method($($arg),*),
Self::VStack(n) => n.$method($($arg),*),
Self::HStack(n) => n.$method($($arg),*),
Self::ScrollView(n) => n.$method($($arg),*),
Self::Grid(n) => n.$method($($arg),*),
Self::Portal(n) => n.$method($($arg),*),
#[cfg(feature = "big-text")]
Self::BigText(n) => n.$method($($arg),*),
Self::ZStack(n) => n.$method($($arg),*),
Self::Center(n) => n.$method($($arg),*),
Self::CenterPin(n) => n.$method($($arg),*),
Self::Animated(n) => n.$method($($arg),*),
Self::DragSource(n) => n.$method($($arg),*),
Self::DropTarget(n) => n.$method($($arg),*),
Self::EffectScope(n) => n.$method($($arg),*),
Self::Frame(n) => n.$method($($arg),*),
Self::Group(n) => n.$method($($arg),*),
Self::MouseRegion(n) => n.$method($($arg),*),
Self::Popover(n) => n.$method($($arg),*),
}
};
}
#[derive(Clone)]
pub(crate) enum NodeKind {
Text(crate::widgets::internal::TextNode),
#[cfg(feature = "big-text")]
BigText(BigTextNode),
AsciiCanvas(AsciiCanvasNode),
Button(crate::widgets::internal::ButtonNode),
Input(crate::widgets::internal::InputNode),
#[cfg(feature = "image")]
Image(ImageNode),
TextArea(Box<crate::widgets::internal::TextAreaNode>),
HexArea(HexAreaNode),
#[cfg(feature = "terminal")]
Terminal(TerminalNode),
Popover(crate::widgets::internal::PopoverNode),
List(crate::widgets::internal::ListNode),
Table(TableNode),
Tabs(TabsNode),
DraggableTabBar(DraggableTabBarNode),
Sparkline(SparklineNode),
Chart(ChartNode),
Graph(GraphRenderNode),
SequenceDiagram(SequenceDiagramNode),
Flowchart(Box<FlowchartNode>),
ClassDiagram(Box<ClassDiagramNode>),
StateDiagram(Box<StateDiagramNode>),
ErDiagram(Box<ErDiagramNode>),
GanttDiagram(Box<GanttDiagramNode>),
StatusBarLayout(StatusBarLayoutNode),
Heatmap(HeatmapNode),
Group(GroupNode),
EffectScope(EffectScopeNode),
Animated(AnimatedNode),
DragSource(DragSourceNode),
DropTarget(DropTargetNode),
MouseRegion(MouseRegionNode),
ScrollView(ScrollViewNode),
PanView(PanViewNode),
VStack(StackNode),
HStack(StackNode),
Grid(GridNode),
Flow(FlowNode),
Canvas(CanvasNode),
ZStack(ZStackNode),
Center(crate::widgets::internal::CenterNode),
CenterPin(CenterPinNode),
Frame(FrameNode),
Divider(crate::widgets::internal::DividerNode),
Spacer(crate::widgets::internal::SpacerNode),
Checkbox(CheckboxNode),
ProgressBar(ProgressNode),
Spinner(SpinnerNode),
Slider(SliderNode),
Splitter(SplitterNode),
DocumentView(Box<DocumentViewNode>),
Portal(crate::overlay::PortalNode),
}
impl WidgetNode for NodeKind {
fn is_focusable(&self) -> bool {
node_kind_delegate_match!(self, is_focusable())
}
fn in_tab_order(&self) -> bool {
node_kind_delegate_match!(self, in_tab_order())
}
fn has_on_click(&self) -> bool {
node_kind_delegate_match!(self, has_on_click())
}
fn has_on_mouse_move(&self) -> bool {
node_kind_delegate_match!(self, has_on_mouse_move())
}
fn is_hoverable(&self) -> bool {
node_kind_delegate_match!(self, is_hoverable())
}
fn is_hoverable_for_theme(&self, theme: &Theme) -> bool {
node_kind_delegate_match!(self, is_hoverable_for_theme(theme))
}
fn hit_test_refinement(&self, x: i16, y: i16, rect: Rect) -> Option<bool> {
node_kind_delegate_match!(self, hit_test_refinement(x, y, rect))
}
fn hover_test_refinement(&self, x: i16, y: i16, rect: Rect) -> Option<bool> {
node_kind_delegate_match!(self, hover_test_refinement(x, y, rect))
}
fn scrollbar_zones(
&self,
id: NodeId,
rect: Rect,
parent_border_x: Option<i16>,
parent_border_y: Option<i16>,
) -> Vec<ScrollbarZone> {
node_kind_delegate_match!(
self,
scrollbar_zones(id, rect, parent_border_x, parent_border_y)
)
}
}
impl From<Button> for NodeKind {
fn from(value: Button) -> Self {
NodeKind::Button(crate::widgets::internal::ButtonNode::from(value))
}
}
impl From<Input> for NodeKind {
fn from(value: Input) -> Self {
NodeKind::Input(crate::widgets::internal::reconcile_input(&value))
}
}
#[cfg(feature = "image")]
impl From<Image> for NodeKind {
fn from(value: Image) -> Self {
NodeKind::Image(crate::widgets::internal::ImageNode::from(value))
}
}
impl From<TextArea> for NodeKind {
fn from(value: TextArea) -> Self {
NodeKind::TextArea(Box::new(crate::widgets::internal::TextAreaNode::from(
value,
)))
}
}
impl From<HexArea> for NodeKind {
fn from(value: HexArea) -> Self {
NodeKind::HexArea(HexAreaNode::from(value))
}
}
impl From<Table> for NodeKind {
fn from(value: Table) -> Self {
NodeKind::Table(crate::widgets::internal::TableNode::from(value))
}
}
impl From<Tabs> for NodeKind {
fn from(value: Tabs) -> Self {
NodeKind::Tabs(TabsNode::from(value))
}
}
impl From<DraggableTabBar> for NodeKind {
fn from(value: DraggableTabBar) -> Self {
NodeKind::DraggableTabBar(DraggableTabBarNode::from(value))
}
}
impl From<Sparkline> for NodeKind {
fn from(value: Sparkline) -> Self {
NodeKind::Sparkline(SparklineNode::from(value))
}
}
impl From<Chart> for NodeKind {
fn from(value: Chart) -> Self {
NodeKind::Chart(ChartNode::from(value))
}
}
impl From<Graph> for NodeKind {
fn from(value: Graph) -> Self {
NodeKind::Graph(GraphRenderNode::from(value))
}
}
impl From<SequenceDiagram> for NodeKind {
fn from(value: SequenceDiagram) -> Self {
NodeKind::SequenceDiagram(SequenceDiagramNode::from(value))
}
}
impl From<Flowchart> for NodeKind {
fn from(value: Flowchart) -> Self {
NodeKind::Flowchart(Box::new(FlowchartNode::from(value)))
}
}
impl From<ClassDiagram> for NodeKind {
fn from(value: ClassDiagram) -> Self {
NodeKind::ClassDiagram(Box::new(ClassDiagramNode::from(value)))
}
}
impl From<StateDiagram> for NodeKind {
fn from(value: StateDiagram) -> Self {
NodeKind::StateDiagram(Box::new(StateDiagramNode::from(value)))
}
}
impl From<ErDiagram> for NodeKind {
fn from(value: ErDiagram) -> Self {
NodeKind::ErDiagram(Box::new(ErDiagramNode::from(value)))
}
}
impl From<GanttDiagram> for NodeKind {
fn from(value: GanttDiagram) -> Self {
NodeKind::GanttDiagram(Box::new(GanttDiagramNode::from(value)))
}
}
impl From<Heatmap> for NodeKind {
fn from(value: Heatmap) -> Self {
NodeKind::Heatmap(HeatmapNode::from(value))
}
}
impl From<Checkbox> for NodeKind {
fn from(value: Checkbox) -> Self {
NodeKind::Checkbox(crate::widgets::internal::CheckboxNode::from(value))
}
}
impl From<ProgressBar> for NodeKind {
fn from(value: ProgressBar) -> Self {
NodeKind::ProgressBar(crate::widgets::internal::ProgressNode::from(value))
}
}
impl From<Spinner> for NodeKind {
fn from(value: Spinner) -> Self {
NodeKind::Spinner(crate::widgets::internal::SpinnerNode::from(value))
}
}
impl From<Slider> for NodeKind {
fn from(value: Slider) -> Self {
NodeKind::Slider(crate::widgets::internal::SliderNode::from(value))
}
}
impl From<Splitter> for NodeKind {
fn from(value: Splitter) -> Self {
NodeKind::Splitter(crate::widgets::internal::SplitterNode::from(value))
}
}
impl From<AsciiCanvas> for NodeKind {
fn from(value: AsciiCanvas) -> Self {
NodeKind::AsciiCanvas(AsciiCanvasNode::from(value))
}
}
impl From<EffectScope> for NodeKind {
fn from(value: EffectScope) -> Self {
NodeKind::EffectScope(EffectScopeNode::from(value))
}
}
impl From<Animated> for NodeKind {
fn from(value: Animated) -> Self {
NodeKind::Animated(AnimatedNode::from(value))
}
}
impl From<DragSource> for NodeKind {
fn from(value: DragSource) -> Self {
NodeKind::DragSource(DragSourceNode::from(value))
}
}
impl From<DropTarget> for NodeKind {
fn from(value: DropTarget) -> Self {
NodeKind::DropTarget(DropTargetNode::from(value))
}
}
impl From<MouseRegion> for NodeKind {
fn from(value: MouseRegion) -> Self {
NodeKind::MouseRegion(MouseRegionNode::from(value))
}
}
impl From<PanView> for NodeKind {
fn from(value: PanView) -> Self {
NodeKind::PanView(PanViewNode::from(value))
}
}