mirror of
https://github.com/danbulant/cushy
synced 2026-06-15 04:21:06 +00:00
Started a List widget
a la HTML's <ul> tag.
This commit is contained in:
parent
1b97b39857
commit
c2bd9911ca
3 changed files with 100 additions and 0 deletions
|
|
@ -39,6 +39,7 @@ use crate::utils::IgnorePoison;
|
|||
use crate::value::{Dynamic, Generation, IntoDynamic, IntoValue, Validation, Value};
|
||||
use crate::widgets::checkbox::{Checkable, CheckboxState};
|
||||
use crate::widgets::layers::{OverlayLayer, Tooltipped};
|
||||
use crate::widgets::list::List;
|
||||
use crate::widgets::{
|
||||
Align, Button, Checkbox, Collapse, Container, Disclose, Expand, Layers, Resize, Scroll, Space,
|
||||
Stack, Style, Themed, ThemedMode, Validated, Wrap,
|
||||
|
|
@ -2036,6 +2037,12 @@ impl WidgetList {
|
|||
Wrap::new(self)
|
||||
}
|
||||
|
||||
/// Returns `self` as an unordered [`List`].
|
||||
#[must_use]
|
||||
pub fn into_list(self) -> List {
|
||||
List::new(self)
|
||||
}
|
||||
|
||||
/// Synchronizes this list of children with another collection.
|
||||
///
|
||||
/// This function updates `collection` by calling `change_fn` for each
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ pub mod image;
|
|||
pub mod input;
|
||||
pub mod label;
|
||||
pub mod layers;
|
||||
pub mod list;
|
||||
mod mode_switch;
|
||||
pub mod progress;
|
||||
pub mod radio;
|
||||
|
|
|
|||
92
src/widgets/list.rs
Normal file
92
src/widgets/list.rs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
//! A list of elements with optional item indicators.
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::grid::GridWidgets;
|
||||
use super::input::CowString;
|
||||
use super::Grid;
|
||||
use crate::value::{IntoValue, MapEach, Source, Value};
|
||||
use crate::widget::{MakeWidget, WidgetInstance, WidgetList};
|
||||
|
||||
/// A list of items displayed with an optional item indicator.
|
||||
pub struct List {
|
||||
style: Value<ListStyle>,
|
||||
children: Value<WidgetList>,
|
||||
}
|
||||
|
||||
impl List {
|
||||
/// Returns a new list with the default [`ListStyle`]/
|
||||
pub fn new(children: impl IntoValue<WidgetList>) -> Self {
|
||||
Self {
|
||||
children: children.into_value(),
|
||||
style: Value::Constant(ListStyle::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The style of a [`List`] widget's item indicators.
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub enum ListStyle {
|
||||
#[default]
|
||||
Disc,
|
||||
Custom(Arc<dyn ListIndicator>),
|
||||
}
|
||||
|
||||
impl PartialEq for ListStyle {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Self::Custom(l0), Self::Custom(r0)) => Arc::ptr_eq(l0, r0),
|
||||
_ => core::mem::discriminant(self) == core::mem::discriminant(other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`ListStyle`] implementation that provides an optional indicator for a
|
||||
/// given list index.
|
||||
pub trait ListIndicator: Debug + Sync + Send + 'static {
|
||||
/// Returns the indicator to use at `index`.
|
||||
fn list_indicator(&self, index: usize) -> Option<CowString>;
|
||||
}
|
||||
|
||||
impl ListIndicator for ListStyle {
|
||||
fn list_indicator(&self, index: usize) -> Option<CowString> {
|
||||
match self {
|
||||
ListStyle::Disc => Some(CowString::new("\u{2022}")),
|
||||
ListStyle::Custom(style) => style.list_indicator(index),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MakeWidget for List {
|
||||
fn make_widget(self) -> WidgetInstance {
|
||||
let rows = match (self.children, self.style) {
|
||||
(children, Value::Constant(style)) => {
|
||||
children.map_each(move |children| build_grid_widgets(&style, children))
|
||||
}
|
||||
(Value::Dynamic(children), Value::Dynamic(style)) => Value::Dynamic(
|
||||
(&style, &children)
|
||||
.map_each(|(style, children)| build_grid_widgets(style, children)),
|
||||
),
|
||||
(Value::Constant(children), Value::Dynamic(style)) => {
|
||||
Value::Dynamic(style.map_each(move |style| build_grid_widgets(style, &children)))
|
||||
}
|
||||
};
|
||||
Grid::from_rows(rows).make_widget()
|
||||
}
|
||||
}
|
||||
|
||||
fn build_grid_widgets(style: &ListStyle, children: &WidgetList) -> GridWidgets<2> {
|
||||
// This is horrible. We should be be using synchronize_with to avoid
|
||||
// recreating the gridwidgets every time.
|
||||
children
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, child)| {
|
||||
(
|
||||
style.list_indicator(index).unwrap_or_default(),
|
||||
child.clone().align_left().make_widget(),
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
Loading…
Reference in a new issue