Skip to content

Commit

Permalink
updated selection list to latested Iced and added a Selection ID retu…
Browse files Browse the repository at this point in the history
…rn and a manual selection override
  • Loading branch information
genusistimelord committed Jul 25, 2023
1 parent 9955bc6 commit 44f6d4c
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 101 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ default = [
#"tabs",
#"time_picker",
#"wrap",
#"selection_list",
"selection_list",
"split",
#"menu",
#"quad",
Expand Down Expand Up @@ -103,7 +103,7 @@ members = [
#"examples/time_picker",
#"examples/wrap",
"examples/number_input",
#"examples/selection_list",
"examples/selection_list",
"examples/split",
"examples/split_scroller",
#"examples/menu",
Expand Down
37 changes: 30 additions & 7 deletions examples/selection_list/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use iced::{
widget::{Column, Container, Space, Text},
Alignment, Element, Length, Sandbox, Settings,
widget::{button, Column, Container, Space, Text},
Alignment, Element, Font, Length, Sandbox, Settings,
};
use iced_aw::{selection_list::SelectionList, SelectionListStyles};

Expand All @@ -12,11 +12,15 @@ pub fn main() -> iced::Result {
struct Example {
vec: Vec<String>,
selected_language: String,
selected_index: usize,
manual_select: Option<usize>,
}

#[derive(Debug, Clone)]
enum Message {
LanguageSelected(String),
LanguageSelected((usize, String)),
AddAtSelection,
ManualSelection,
}

impl Sandbox for Example {
Expand All @@ -41,13 +45,28 @@ impl Sandbox for Example {

fn update(&mut self, message: Message) {
match message {
Message::LanguageSelected(language) => {
self.selected_language = language.clone();
Message::LanguageSelected((index, language)) => {
self.selected_language = language;
self.selected_index = index;
self.manual_select = None;

if language == "Rust" {
if self.selected_language == "Rust" {
self.vec.push("Rusty".into());
}
}
Message::AddAtSelection => {
self.vec
.insert(self.selected_index, "Java OH NOES!".to_owned());
self.selected_language.clear();
self.manual_select = None;
}
Message::ManualSelection => {
if let Some(option) = self.vec.get(0) {
self.selected_language = option.to_owned();
self.selected_index = 0;
self.manual_select = Some(0);
}
}
}
}

Expand All @@ -58,6 +77,8 @@ impl Sandbox for Example {
12.0,
5.0,
SelectionListStyles::Default,
self.manual_select,
Font::default(),
)
.width(Length::Shrink)
.height(Length::Fixed(100.0));
Expand All @@ -68,7 +89,9 @@ impl Sandbox for Example {
.spacing(10)
.push(selection_list)
.push(Text::new("Which is your favorite language?"))
.push(Text::new(format!("{:?}", self.selected_language)));
.push(Text::new(format!("{:?}", self.selected_language)))
.push(button("press to add at selection").on_press(Message::AddAtSelection))
.push(button("Manual select Index 2").on_press(Message::ManualSelection));

content = content.push(Space::with_height(Length::Fixed(800.0)));

Expand Down
4 changes: 2 additions & 2 deletions src/native/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ pub use date_picker::DatePicker;
pub mod selection_list;
#[cfg(feature = "selection_list")]
/// A widget for selecting a single value from a dynamic scrollable list of options.
pub type SelectionList<'a, T, Message, Backend, Theme> =
selection_list::SelectionList<'a, T, Message, Renderer<Backend, Theme>>;
pub type SelectionList<'a, T, Message, Renderer> =
selection_list::SelectionList<'a, T, Message, Renderer>;
#[cfg(feature = "selection_list")]
pub use selection_list::List;

Expand Down
101 changes: 54 additions & 47 deletions src/native/selection_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,34 @@
pub mod list;
use crate::style::selection_list::StyleSheet;

use iced_native::{
event,
layout::{Limits, Node},
mouse, renderer, Clipboard, Event, Layout, Length, Point, Rectangle, Shell, Size,
use iced_widget::{
container,
core::{
self, event, layout,
mouse::{self, Cursor},
renderer,
widget::Tree,
Clipboard, Element, Event, Layout, Length, Rectangle, Shell, Size, Widget,
},
runtime::Font,
scrollable, text,
text::LineHeight,
Container, Scrollable,
};

use iced_native::widget::tree::Tree;
use iced_native::widget::{Container, Scrollable};
use iced_native::{Element, Widget};

pub use list::List;
use std::borrow::Cow;
use std::marker::PhantomData;
use std::{borrow::Cow, hash::Hash};

/// A widget for selecting a single value from a dynamic scrollable list of options.
#[allow(missing_debug_implementations)]
#[allow(clippy::type_repetition_in_bounds)]
pub struct SelectionList<'a, T, Message, Renderer>
pub struct SelectionList<'a, T, Message, Renderer = crate::Renderer>
where
T: Clone + ToString,
T: Clone + ToString + Eq + Hash,
[T]: ToOwned<Owned = Vec<T>>,
Renderer: iced_native::Renderer + iced_native::text::Renderer<Font = iced_native::Font>,
Renderer::Theme: StyleSheet + iced_style::container::StyleSheet,
Renderer: core::Renderer + core::text::Renderer<Font = core::Font>,
Renderer::Theme: StyleSheet + container::StyleSheet,
{
/// Container for Rendering List.
container: Container<'a, Message, Renderer>,
Expand All @@ -48,10 +53,9 @@ where
impl<'a, T, Message, Renderer> SelectionList<'a, T, Message, Renderer>
where
Message: 'a + Clone,
Renderer: 'a + iced_native::Renderer + iced_native::text::Renderer<Font = iced_native::Font>,
Renderer::Theme:
StyleSheet + iced_style::container::StyleSheet + iced_style::scrollable::StyleSheet,
T: Clone + ToString + Eq,
Renderer: 'a + core::Renderer + core::text::Renderer<Font = core::Font>,
Renderer::Theme: StyleSheet + container::StyleSheet + scrollable::StyleSheet,
T: Clone + ToString + Eq + Hash,
[T]: ToOwned<Owned = Vec<T>>,
{
/// Creates a new [`SelectionList`] with the given list of `options`,
Expand All @@ -60,23 +64,24 @@ where
/// to set those.
pub fn new(
options: impl Into<Cow<'a, [T]>>,
on_selected: impl Fn(T) -> Message + 'static,
on_selected: impl Fn((usize, T)) -> Message + 'static,
) -> Self {
let options = options.into();
let container = Container::new(Scrollable::new(List {
options: options.clone(),
font: iced_graphics::Font::default(),
font: Font::default(),
text_size: 12.0,
padding: 5.0,
style: <Renderer::Theme as StyleSheet>::Style::default(),
on_selected: Box::new(on_selected),
selected: None,
phantomdata: PhantomData,
}))
.padding(1);

Self {
options,
font: iced_graphics::Font::default(),
font: Font::default(),
style: <Renderer::Theme as StyleSheet>::Style::default(),
container,
width: Length::Fill,
Expand All @@ -88,29 +93,32 @@ where

/// Creates a new [`SelectionList`] with the given list of `options`,
/// the current selected value, the message to produce when an option is
/// selected, the `style`, `text_size` and `padding`.
/// selected, the `style`, `text_size`, `padding` and `font`.
pub fn new_with(
options: impl Into<Cow<'a, [T]>>,
on_selected: impl Fn(T) -> Message + 'static,
on_selected: impl Fn((usize, T)) -> Message + 'static,
text_size: f32,
padding: f32,
style: <Renderer::Theme as StyleSheet>::Style,
selected: Option<usize>,
font: Font,
) -> Self {
let options = options.into();
let container = Container::new(Scrollable::new(List {
options: options.clone(),
font: iced_graphics::Font::default(),
font,
text_size,
padding,
style,
selected,
on_selected: Box::new(on_selected),
phantomdata: PhantomData,
}))
.padding(1);

Self {
options,
font: iced_graphics::Font::default(),
font,
style,
container,
width: Length::Fill,
Expand Down Expand Up @@ -144,10 +152,10 @@ where

impl<'a, T, Message, Renderer> Widget<Message, Renderer> for SelectionList<'a, T, Message, Renderer>
where
T: 'a + Clone + ToString + Eq,
T: 'a + Clone + ToString + Eq + Hash,
Message: 'static,
Renderer: iced_native::Renderer + iced_native::text::Renderer<Font = iced_native::Font> + 'a,
Renderer::Theme: StyleSheet + iced_style::container::StyleSheet,
Renderer: core::Renderer + core::text::Renderer<Font = core::Font> + 'a,
Renderer::Theme: StyleSheet + container::StyleSheet,
{
fn children(&self) -> Vec<Tree> {
vec![Tree::new(&self.container as &dyn Widget<_, _>)]
Expand All @@ -165,7 +173,7 @@ where
Length::Shrink
}

fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node {
fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> layout::Node {
use std::f32;

let limits = limits.width(self.width).height(self.height);
Expand All @@ -176,14 +184,16 @@ where

labels
.map(|label| {
let (width, _) = renderer.measure(
let size = renderer.measure(
&label,
self.text_size,
LineHeight::default(),
self.font,
Size::new(f32::INFINITY, f32::INFINITY),
text::Shaping::Advanced,
);

width.round() as u32 + self.padding as u32 * 2
size.width.round() as u32 + self.padding as u32 * 2
})
.max()
.unwrap_or(100)
Expand All @@ -195,18 +205,19 @@ where

let content = self.container.layout(renderer, &limits);
let size = limits.resolve(content.size());
Node::with_children(size, vec![content])
layout::Node::with_children(size, vec![content])
}

fn on_event(
&mut self,
state: &mut Tree,
event: Event,
layout: Layout<'_>,
cursor_position: Point,
cursor: Cursor,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
shell: &mut Shell<Message>,
viewport: &Rectangle,
) -> event::Status {
self.container.on_event(
&mut state.children[0],
Expand All @@ -215,38 +226,34 @@ where
.children()
.next()
.expect("Scrollable Child Missing in Selection List"),
cursor_position,
cursor,
renderer,
clipboard,
shell,
viewport,
)
}

fn mouse_interaction(
&self,
state: &Tree,
layout: Layout<'_>,
cursor_position: Point,
cursor: Cursor,
viewport: &Rectangle,
renderer: &Renderer,
) -> mouse::Interaction {
self.container.mouse_interaction(
&state.children[0],
layout,
cursor_position,
viewport,
renderer,
)
self.container
.mouse_interaction(&state.children[0], layout, cursor, viewport, renderer)
}

fn draw(
&self,
state: &Tree,
renderer: &mut Renderer,
theme: &Renderer::Theme,
style: &iced_native::renderer::Style,
style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
cursor: Cursor,
_viewport: &Rectangle,
) {
renderer.fill_quad(
Expand All @@ -268,7 +275,7 @@ where
.children()
.next()
.expect("Scrollable Child Missing in Selection List"),
cursor_position,
cursor,
&layout.bounds(),
);
}
Expand All @@ -277,10 +284,10 @@ where
impl<'a, T, Message, Renderer> From<SelectionList<'a, T, Message, Renderer>>
for Element<'a, Message, Renderer>
where
T: Clone + ToString + Eq,
T: Clone + ToString + Eq + Hash,
Message: 'static,
Renderer: 'a + iced_native::Renderer + iced_native::text::Renderer<Font = iced_native::Font>,
Renderer::Theme: StyleSheet + iced_style::container::StyleSheet,
Renderer: 'a + core::Renderer + core::text::Renderer<Font = core::Font>,
Renderer::Theme: StyleSheet + container::StyleSheet,
{
fn from(selection_list: SelectionList<'a, T, Message, Renderer>) -> Self {
Element::new(selection_list)
Expand Down
Loading

0 comments on commit 44f6d4c

Please sign in to comment.