use std::ops::{Deref, DerefMut};
use kas::draw::{Draw, Pass};
use kas::geom::{Coord, Rect, Size};
use kas::layout::{AxisInfo, Margins, SizeRules};
use kas::{Align, Direction};
pub enum ClipRegion {
Popup,
Scroll,
}
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq)]
pub struct InputState {
pub disabled: bool,
pub error: bool,
pub hover: bool,
pub depress: bool,
pub nav_focus: bool,
pub char_focus: bool,
}
impl std::ops::BitOr for InputState {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
InputState {
disabled: self.disabled || rhs.disabled,
error: self.error || rhs.error,
hover: self.hover || rhs.hover,
depress: self.depress || rhs.depress,
nav_focus: self.nav_focus || rhs.nav_focus,
char_focus: self.char_focus || rhs.char_focus,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub enum TextClass {
Label,
Button,
Edit,
EditMulti,
}
impl Default for TextClass {
fn default() -> Self {
TextClass::Label
}
}
pub trait SizeHandle {
fn scale_factor(&self) -> f32;
fn frame(&self) -> Size;
fn menu_frame(&self) -> Size;
fn inner_margin(&self) -> Size;
fn outer_margins(&self) -> Margins;
fn line_height(&self, class: TextClass) -> u32;
fn text_bound(&mut self, text: &str, class: TextClass, axis: AxisInfo) -> SizeRules;
fn button_surround(&self) -> (Size, Size);
fn edit_surround(&self) -> (Size, Size);
fn checkbox(&self) -> Size;
fn radiobox(&self) -> Size;
fn scrollbar(&self) -> (Size, u32);
fn slider(&self) -> (Size, u32);
}
pub trait DrawHandle {
fn draw_device(&mut self) -> (Pass, Coord, &mut dyn Draw);
fn clip_region(
&mut self,
rect: Rect,
offset: Coord,
class: ClipRegion,
f: &mut dyn FnMut(&mut dyn DrawHandle),
);
fn target_rect(&self) -> Rect;
fn outer_frame(&mut self, rect: Rect);
fn menu_frame(&mut self, rect: Rect);
fn separator(&mut self, rect: Rect);
fn text(&mut self, rect: Rect, text: &str, class: TextClass, align: (Align, Align));
fn menu_entry(&mut self, rect: Rect, state: InputState);
fn button(&mut self, rect: Rect, state: InputState);
fn edit_box(&mut self, rect: Rect, state: InputState);
fn checkbox(&mut self, rect: Rect, checked: bool, state: InputState);
fn radiobox(&mut self, rect: Rect, checked: bool, state: InputState);
fn scrollbar(&mut self, rect: Rect, h_rect: Rect, dir: Direction, state: InputState);
fn slider(&mut self, rect: Rect, h_rect: Rect, dir: Direction, state: InputState);
}
impl<S: SizeHandle> SizeHandle for Box<S> {
fn scale_factor(&self) -> f32 {
self.deref().scale_factor()
}
fn frame(&self) -> Size {
self.deref().frame()
}
fn menu_frame(&self) -> Size {
self.deref().menu_frame()
}
fn inner_margin(&self) -> Size {
self.deref().inner_margin()
}
fn outer_margins(&self) -> Margins {
self.deref().outer_margins()
}
fn line_height(&self, class: TextClass) -> u32 {
self.deref().line_height(class)
}
fn text_bound(&mut self, text: &str, class: TextClass, axis: AxisInfo) -> SizeRules {
self.deref_mut().text_bound(text, class, axis)
}
fn button_surround(&self) -> (Size, Size) {
self.deref().button_surround()
}
fn edit_surround(&self) -> (Size, Size) {
self.deref().edit_surround()
}
fn checkbox(&self) -> Size {
self.deref().checkbox()
}
fn radiobox(&self) -> Size {
self.deref().radiobox()
}
fn scrollbar(&self) -> (Size, u32) {
self.deref().scrollbar()
}
fn slider(&self) -> (Size, u32) {
self.deref().slider()
}
}
#[cfg(feature = "stack_dst")]
impl<S> SizeHandle for stack_dst::ValueA<dyn SizeHandle, S>
where
S: Default + Copy + AsRef<[usize]> + AsMut<[usize]>,
{
fn scale_factor(&self) -> f32 {
self.deref().scale_factor()
}
fn frame(&self) -> Size {
self.deref().frame()
}
fn menu_frame(&self) -> Size {
self.deref().menu_frame()
}
fn inner_margin(&self) -> Size {
self.deref().inner_margin()
}
fn outer_margins(&self) -> Margins {
self.deref().outer_margins()
}
fn line_height(&self, class: TextClass) -> u32 {
self.deref().line_height(class)
}
fn text_bound(&mut self, text: &str, class: TextClass, axis: AxisInfo) -> SizeRules {
self.deref_mut().text_bound(text, class, axis)
}
fn button_surround(&self) -> (Size, Size) {
self.deref().button_surround()
}
fn edit_surround(&self) -> (Size, Size) {
self.deref().edit_surround()
}
fn checkbox(&self) -> Size {
self.deref().checkbox()
}
fn radiobox(&self) -> Size {
self.deref().radiobox()
}
fn scrollbar(&self) -> (Size, u32) {
self.deref().scrollbar()
}
fn slider(&self) -> (Size, u32) {
self.deref().slider()
}
}
impl<H: DrawHandle> DrawHandle for Box<H> {
fn draw_device(&mut self) -> (Pass, Coord, &mut dyn Draw) {
self.deref_mut().draw_device()
}
fn clip_region(
&mut self,
rect: Rect,
offset: Coord,
class: ClipRegion,
f: &mut dyn FnMut(&mut dyn DrawHandle),
) {
self.deref_mut().clip_region(rect, offset, class, f)
}
fn target_rect(&self) -> Rect {
self.deref().target_rect()
}
fn outer_frame(&mut self, rect: Rect) {
self.deref_mut().outer_frame(rect);
}
fn menu_frame(&mut self, rect: Rect) {
self.deref_mut().menu_frame(rect);
}
fn separator(&mut self, rect: Rect) {
self.deref_mut().separator(rect);
}
fn text(&mut self, rect: Rect, text: &str, class: TextClass, align: (Align, Align)) {
self.deref_mut().text(rect, text, class, align)
}
fn menu_entry(&mut self, rect: Rect, state: InputState) {
self.deref_mut().menu_entry(rect, state)
}
fn button(&mut self, rect: Rect, state: InputState) {
self.deref_mut().button(rect, state)
}
fn edit_box(&mut self, rect: Rect, state: InputState) {
self.deref_mut().edit_box(rect, state)
}
fn checkbox(&mut self, rect: Rect, checked: bool, state: InputState) {
self.deref_mut().checkbox(rect, checked, state)
}
fn radiobox(&mut self, rect: Rect, checked: bool, state: InputState) {
self.deref_mut().radiobox(rect, checked, state)
}
fn scrollbar(&mut self, rect: Rect, h_rect: Rect, dir: Direction, state: InputState) {
self.deref_mut().scrollbar(rect, h_rect, dir, state)
}
fn slider(&mut self, rect: Rect, h_rect: Rect, dir: Direction, state: InputState) {
self.deref_mut().slider(rect, h_rect, dir, state)
}
}
#[cfg(feature = "stack_dst")]
impl<S> DrawHandle for stack_dst::ValueA<dyn DrawHandle, S>
where
S: Default + Copy + AsRef<[usize]> + AsMut<[usize]>,
{
fn draw_device(&mut self) -> (Pass, Coord, &mut dyn Draw) {
self.deref_mut().draw_device()
}
fn clip_region(
&mut self,
rect: Rect,
offset: Coord,
class: ClipRegion,
f: &mut dyn FnMut(&mut dyn DrawHandle),
) {
self.deref_mut().clip_region(rect, offset, class, f)
}
fn target_rect(&self) -> Rect {
self.deref().target_rect()
}
fn outer_frame(&mut self, rect: Rect) {
self.deref_mut().outer_frame(rect);
}
fn menu_frame(&mut self, rect: Rect) {
self.deref_mut().menu_frame(rect);
}
fn separator(&mut self, rect: Rect) {
self.deref_mut().separator(rect);
}
fn text(&mut self, rect: Rect, text: &str, class: TextClass, align: (Align, Align)) {
self.deref_mut().text(rect, text, class, align)
}
fn menu_entry(&mut self, rect: Rect, state: InputState) {
self.deref_mut().menu_entry(rect, state)
}
fn button(&mut self, rect: Rect, state: InputState) {
self.deref_mut().button(rect, state)
}
fn edit_box(&mut self, rect: Rect, state: InputState) {
self.deref_mut().edit_box(rect, state)
}
fn checkbox(&mut self, rect: Rect, checked: bool, state: InputState) {
self.deref_mut().checkbox(rect, checked, state)
}
fn radiobox(&mut self, rect: Rect, checked: bool, state: InputState) {
self.deref_mut().radiobox(rect, checked, state)
}
fn scrollbar(&mut self, rect: Rect, h_rect: Rect, dir: Direction, state: InputState) {
self.deref_mut().scrollbar(rect, h_rect, dir, state)
}
fn slider(&mut self, rect: Rect, h_rect: Rect, dir: Direction, state: InputState) {
self.deref_mut().slider(rect, h_rect, dir, state)
}
}