Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Examples and documentation for List Widget #2302

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ You can find its changes [documented below](#070---2021-01-01).
- Fix `Controller` links for `Click` ([#2158] by [@yrns])
- Delete inaccurate line for `KeyEvent` ([#2247] by [@amtep])
- Added examples in `TextBox` ([#2284] by [@ThomasMcandrew])
- Added examples in `List` ([#2302] by [@ThomasMcandrew])

### Examples
- Add readme ([#1423] by [@JAicewizard])
Expand Down Expand Up @@ -867,6 +868,7 @@ Last release without a changelog :(
[#2247]: https://github.com/linebender/druid/pull/2247
[#2274]: https://github.com/linebender/druid/pull/2274
[#2284]: https://github.com/linebender/druid/pull/2284
[#2302]: https://github.com/linebender/druid/pull/2302

[Unreleased]: https://github.com/linebender/druid/compare/v0.7.0...master
[0.7.0]: https://github.com/linebender/druid/compare/v0.6.0...v0.7.0
Expand Down
155 changes: 155 additions & 0 deletions druid/src/widget/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,126 @@ use crate::{
};

/// A list widget for a variable-size collection of items.
/// For a static sized collection of items use [`Flex`].
/// The best data structure to use with the list widget is [`Vector`] from the [`im`] feature.
/// To include the [`im`] feature, update Cargo.toml
/// ```ignore
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// ```ignore
/// ```toml

Marking the code as toml gets you better highlighting.

/// [dependencies]
/// // before
/// druid = "0.7.0"
/// // after
/// druid = { version = "0.7.0", features = ["im"] }
/// ```
///
/// # Examples
///
/// ## Define the data
///
/// ```
/// # use druid::{ Data, Lens };
/// use druid::im::Vector;
/// #[derive(Clone, Data, Lens)]
/// struct AppState {
/// list_data: Vector<String>,
/// }
/// ```
/// ## Create initial State
///
/// ```
/// # use druid::{ Data, Lens};
/// # use druid::im::Vector;
/// # #[derive(Clone, Data, Lens)]
/// # struct AppState {
/// # list_data: Vector<String>,
/// # }
/// let initial_state = AppState {
/// list_data: Vector::from(
/// vec!(
/// "one".into(),
/// "two".into(),
/// "three".into(),
/// "four".into(),
/// )),
/// };
/// ```
/// ## Create widgets
///
/// ```
/// # use druid::widget::{ Label, List };
/// # use druid::{ Data, Lens, Widget, WidgetExt, Env};
/// # use druid::im::Vector;
/// # #[derive(Clone, Data, Lens)]
/// # struct AppState {
/// # list_data: Vector<String>,
/// # }
/// fn root() -> impl Widget<AppState> {
/// let list = List::new(list_item)
/// .lens(AppState::list_data);
/// list
/// }
///
/// fn list_item() -> impl Widget<String> {
/// let label = Label::new(|data: &String, _env: &Env|
/// data.clone());
/// label
/// }
/// ```
Comment on lines +52 to +100
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole example seems way too big to me. It's the example equivalent of an integration test, where you'd want a unit test.

I'd recommend skipping the AppState data structure and the lensing, and just using Vector<String> in your example.

/// ## Scrollable List
/// Commonly a list should be able to scroll, the [`Scroll`] widget can be used to implement this
/// feature.
/// See docs for more info.
///
/// ```
/// # use druid::widget::{ Label, List, Scroll };
/// # use druid::{ Data, Lens, Widget, WidgetExt, Env};
/// # use druid::im::Vector;
/// # #[derive(Clone, Data, Lens)]
/// # struct AppState {
/// # list_data: Vector<String>,
/// # }
/// # fn list_item() -> impl Widget<String> {
/// # let label = Label::new(|data: &String, _env: &Env|
/// # data.clone());
/// # label
/// # }
/// fn root() -> impl Widget<AppState> {
/// let list = List::new(list_item)
/// .lens(AppState::list_data);
/// Scroll::new(list)
/// }
/// ```
/// ## Complex widgets
/// List can be used with any complex widgets.
/// ```
/// # use druid::widget::{ Label, List };
/// # use druid::{ Data, Lens, Widget, WidgetExt, Env};
/// # use druid::im::Vector;
/// #[derive(Clone, Data, Lens)]
/// struct AppState {
/// list_data: Vector<InnerState>,
/// }
///
/// #[derive(Clone, Data, Lens)]
/// struct InnerState {
/// name: String,
/// }
///
/// fn root() -> impl Widget<AppState> {
/// let list = List::new(list_item)
/// .lens(AppState::list_data);
/// list
/// }
///
/// fn list_item() -> impl Widget<InnerState> {
/// let label = Label::new(|data: &InnerState, _env: &Env|
/// data.name.clone());
/// label
/// }
/// ```
Comment on lines +125 to +152
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should remove that part, or at least make it way shorter. That fact that widgets can be compose doesn't need to be documented in every container widget.

/// [`im`]: https://docs.rs/druid/0.6.0/druid/im/index.html
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the link I am referring to in the description. is there a way to do it like the flex crate below?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my tests, it seems that [`im`] alone works, but only if you build the docs with --feature=im. I wouldn't bother.

/// [`Flex`]: crate::widget::Flex
/// [`Vector`]: https://docs.rs/druid/0.6.0/druid/im/vector/index.html
/// [`Scroll`]: crate::widget::Scroll
pub struct List<T> {
closure: Box<dyn Fn() -> Box<dyn Widget<T>>>,
children: Vec<WidgetPod<T, Box<dyn Widget<T>>>>,
Expand All @@ -45,6 +165,41 @@ pub struct List<T> {
impl<T: Data> List<T> {
/// Create a new list widget. Closure will be called every time when a new child
/// needs to be constructed.
///
/// The list widget can have a function passed in as a closure, or an abstract closure can also
/// be provided.
///
Comment on lines +168 to +171
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part seems superfluous. I think you can assume the vast majority of Rust users will be familiar with how closures work. (And if they aren't, this isn't the place to explain them)

/// # Example
/// ```
/// # use druid::widget::{ Label, List };
/// # use druid::{ Data, Lens, Widget, WidgetExt, Env};
/// # use druid::im::Vector;
/// # #[derive(Clone, Data, Lens)]
/// # struct AppState {
/// # list_data: Vector<String>,
/// # }
/// fn root() -> impl Widget<AppState> {
/// let list = List::new(list_item)
/// .lens(AppState::list_data);
/// list
/// }
///
/// fn list_item() -> impl Widget<String> {
/// let label = Label::new(|data: &String, _env: &Env|
/// data.clone());
/// label
/// }
///
/// //This widget is the same as the two widgets above
/// //combined.
/// fn combined() -> impl Widget<AppState> {
/// let list = List::new(||
/// Label::new(|data: &String, _env: &Env|
/// data.clone()))
/// .lens(AppState::list_data);
/// list
/// }
Comment on lines +193 to +201
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can probably remove the combined function; the other two are descriptive enough on their own.

/// ```
pub fn new<W: Widget<T> + 'static>(closure: impl Fn() -> W + 'static) -> Self {
List {
closure: Box::new(move || Box::new(closure())),
Expand Down