pub mod avatar;
pub mod bar;
pub mod button;
pub mod card;
pub mod checkbox;
pub mod clock;
pub mod container;
pub mod context_menu;
pub mod desktop;
pub mod dropdown;
pub mod icon_button;
pub mod label;
pub mod list_view;
pub mod notification;
pub mod password_field;
pub mod progress;
pub mod scroll_view;
pub mod separator;
pub mod slider;
pub mod spacer;
pub mod spinner;
pub mod switch;
pub mod system_tray;
pub mod tabs;
pub mod textfield;
pub mod tooltip;
pub mod window;
pub mod workspace;
pub mod action_center;
pub mod app_grid;
pub mod battery_indicator;
pub mod calendar;
pub mod chat_window;
pub mod glass_pane;
pub mod network_indicator;
pub mod panel;
pub mod search_bar;
pub mod start_button;
pub mod start_menu;
pub mod taskbar_button;
pub mod volume_control;
pub mod address_bar;
pub mod bookmark_bar;
pub mod browser_tab;
pub mod browser_toolbar;
pub mod download_item;
pub mod find_bar;
pub mod navigation_bar;
use crate::css::{ClassList, ComputedStyle, StyleContext, WidgetState};
use crate::event::{Event, EventResult};
use crate::geometry::{Point, Rect, Size};
use crate::layout::{Constraints, LayoutResult};
use crate::render::Painter;
pub type EventCallback<T = ()> = Option<Box<dyn Fn() -> T + Send + Sync>>;
pub type StringCallback = Option<Box<dyn Fn(&str) + Send + Sync>>;
use std::sync::atomic::{AtomicU64, Ordering};
pub type WidgetId = u64;
static WIDGET_ID_COUNTER: AtomicU64 = AtomicU64::new(1);
pub fn next_widget_id() -> WidgetId {
WIDGET_ID_COUNTER.fetch_add(1, Ordering::SeqCst)
}
pub trait Widget {
fn id(&self) -> WidgetId;
fn type_name(&self) -> &'static str;
fn element_id(&self) -> Option<&str> {
None
}
fn classes(&self) -> &ClassList;
fn state(&self) -> WidgetState;
fn intrinsic_size(&self, ctx: &LayoutContext) -> Size;
fn layout(&mut self, constraints: Constraints, ctx: &LayoutContext) -> LayoutResult;
fn paint(&self, painter: &mut Painter, rect: Rect, ctx: &PaintContext);
fn handle_event(&mut self, _event: &Event, _ctx: &mut EventContext) -> EventResult {
EventResult::Ignored
}
fn style(&self, _ctx: &StyleContext) -> ComputedStyle {
ComputedStyle::default()
}
fn bounds(&self) -> Rect;
fn set_bounds(&mut self, bounds: Rect);
fn hit_test(&self, point: Point) -> bool {
self.bounds().contains(point)
}
fn children(&self) -> &[Box<dyn Widget>] {
&[]
}
fn children_mut(&mut self) -> &mut [Box<dyn Widget>] {
&mut []
}
}
pub struct LayoutContext<'a> {
pub style_ctx: &'a StyleContext<'a>,
pub scale_factor: f32,
}
impl<'a> LayoutContext<'a> {
pub fn new(style_ctx: &'a StyleContext<'a>) -> Self {
Self {
style_ctx,
scale_factor: 1.0,
}
}
pub fn with_scale(mut self, scale: f32) -> Self {
self.scale_factor = scale;
self
}
}
pub struct PaintContext<'a> {
pub style_ctx: &'a StyleContext<'a>,
pub scale_factor: f32,
pub focus_visible: bool,
}
impl<'a> PaintContext<'a> {
pub fn new(style_ctx: &'a StyleContext<'a>) -> Self {
Self {
style_ctx,
scale_factor: 1.0,
focus_visible: false,
}
}
}
pub struct EventContext {
pub focus: Option<WidgetId>,
pub mouse_position: Point,
pub should_redraw: bool,
}
impl EventContext {
pub fn new() -> Self {
Self {
focus: None,
mouse_position: Point::ZERO,
should_redraw: false,
}
}
pub fn request_focus(&mut self, widget_id: WidgetId) {
self.focus = Some(widget_id);
}
pub fn release_focus(&mut self) {
self.focus = None;
}
pub fn request_redraw(&mut self) {
self.should_redraw = true;
}
}
impl Default for EventContext {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug)]
pub struct WidgetBase {
pub id: WidgetId,
pub element_id: Option<String>,
pub classes: ClassList,
pub bounds: Rect,
pub state: WidgetState,
}
impl WidgetBase {
pub fn new() -> Self {
Self {
id: next_widget_id(),
element_id: None,
classes: ClassList::new(),
bounds: Rect::ZERO,
state: WidgetState::default(),
}
}
pub fn with_class(mut self, class: &str) -> Self {
self.classes.add(class);
self
}
pub fn with_id(mut self, id: &str) -> Self {
self.element_id = Some(id.to_string());
self
}
}
impl Default for WidgetBase {
fn default() -> Self {
Self::new()
}
}