use std::fmt::Debug;
use std::ops::{Index, IndexMut};
use kas::prelude::*;
pub type BoxStack<M> = Stack<Box<dyn Widget<Msg = M>>>;
pub type RefStack<'a, M> = Stack<&'a mut dyn Widget<Msg = M>>;
#[handler(send=noauto, msg=<W as event::Handler>::Msg)]
#[widget(children=noauto)]
#[derive(Clone, Default, Debug, Widget)]
pub struct Stack<W: Widget> {
#[widget_core]
core: CoreData,
widgets: Vec<W>,
active: usize,
}
impl<W: Widget> WidgetChildren for Stack<W> {
#[inline]
fn len(&self) -> usize {
self.widgets.len()
}
#[inline]
fn get(&self, index: usize) -> Option<&dyn WidgetConfig> {
self.widgets.get(index).map(|w| w.as_widget())
}
#[inline]
fn get_mut(&mut self, index: usize) -> Option<&mut dyn WidgetConfig> {
self.widgets.get_mut(index).map(|w| w.as_widget_mut())
}
}
impl<W: Widget> Layout for Stack<W> {
fn size_rules(&mut self, size_handle: &mut dyn SizeHandle, axis: AxisInfo) -> SizeRules {
let mut rules = SizeRules::EMPTY;
for child in &mut self.widgets {
rules = rules.max(child.size_rules(size_handle, axis));
}
rules
}
fn set_rect(&mut self, rect: Rect, align: AlignHints) {
self.core.rect = rect;
for child in &mut self.widgets {
child.set_rect(rect, align.clone());
}
}
fn find_id(&self, coord: Coord) -> Option<WidgetId> {
if self.active < self.widgets.len() {
return self.widgets[self.active].find_id(coord);
}
None
}
fn draw(&self, draw_handle: &mut dyn DrawHandle, mgr: &event::ManagerState, disabled: bool) {
let disabled = disabled || self.is_disabled();
if self.active < self.widgets.len() {
self.widgets[self.active].draw(draw_handle, mgr, disabled);
}
}
}
impl<W: Widget> event::SendEvent for Stack<W> {
fn send(&mut self, mgr: &mut Manager, id: WidgetId, event: Event) -> Response<Self::Msg> {
if !self.is_disabled() {
for (index, child) in self.widgets.iter_mut().enumerate() {
if id <= child.id() {
return match child.send(mgr, id, event) {
Response::Focus(rect) => {
*mgr += self.set_active(index);
Response::Focus(rect)
}
r => r,
};
}
}
}
Response::Unhandled(event)
}
}
impl<W: Widget> Stack<W> {
pub fn new(widgets: Vec<W>, active: usize) -> Self {
Stack {
core: Default::default(),
widgets,
active,
}
}
pub fn active_index(&self) -> usize {
self.active
}
pub fn set_active(&mut self, active: usize) -> TkAction {
if self.active == active {
TkAction::None
} else {
self.active = active;
TkAction::RegionMoved
}
}
pub fn active(&self) -> Option<&W> {
if self.active < self.widgets.len() {
Some(&self.widgets[self.active])
} else {
None
}
}
pub fn active_mut(&mut self) -> Option<&mut W> {
if self.active < self.widgets.len() {
Some(&mut self.widgets[self.active])
} else {
None
}
}
pub fn is_empty(&self) -> bool {
self.widgets.is_empty()
}
pub fn len(&self) -> usize {
self.widgets.len()
}
pub fn capacity(&self) -> usize {
self.widgets.capacity()
}
pub fn reserve(&mut self, additional: usize) {
self.widgets.reserve(additional);
}
pub fn clear(&mut self) -> TkAction {
let action = match self.widgets.is_empty() {
true => TkAction::None,
false => TkAction::Reconfigure,
};
self.widgets.clear();
action
}
pub fn push(&mut self, widget: W) -> TkAction {
self.widgets.push(widget);
TkAction::Reconfigure
}
pub fn pop(&mut self) -> (Option<W>, TkAction) {
let action = match self.widgets.is_empty() {
true => TkAction::None,
false => TkAction::Reconfigure,
};
(self.widgets.pop(), action)
}
pub fn insert(&mut self, index: usize, widget: W) -> TkAction {
self.widgets.insert(index, widget);
TkAction::Reconfigure
}
pub fn remove(&mut self, index: usize) -> (W, TkAction) {
let r = self.widgets.remove(index);
(r, TkAction::Reconfigure)
}
pub fn replace(&mut self, index: usize, mut widget: W) -> (W, TkAction) {
std::mem::swap(&mut widget, &mut self.widgets[index]);
(widget, TkAction::Reconfigure)
}
pub fn extend<T: IntoIterator<Item = W>>(&mut self, iter: T) -> TkAction {
let len = self.widgets.len();
self.widgets.extend(iter);
match len == self.widgets.len() {
true => TkAction::None,
false => TkAction::Reconfigure,
}
}
pub fn resize_with<F: Fn(usize) -> W>(&mut self, len: usize, f: F) -> TkAction {
let l0 = self.widgets.len();
if l0 == len {
return TkAction::None;
} else if l0 > len {
self.widgets.truncate(len);
} else {
self.widgets.reserve(len);
for i in l0..len {
self.widgets.push(f(i));
}
}
TkAction::Reconfigure
}
pub fn retain<F: FnMut(&W) -> bool>(&mut self, f: F) -> TkAction {
let len = self.widgets.len();
self.widgets.retain(f);
match len == self.widgets.len() {
true => TkAction::None,
false => TkAction::Reconfigure,
}
}
}
impl<W: Widget> Index<usize> for Stack<W> {
type Output = W;
fn index(&self, index: usize) -> &Self::Output {
&self.widgets[index]
}
}
impl<W: Widget> IndexMut<usize> for Stack<W> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.widgets[index]
}
}