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

Add virtual_list with selections #251

Merged
merged 1 commit into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions examples/layout/src/draggable_sidebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use floem::{
style::{CursorStyle, Position},
view::View,
views::{
container, h_stack, label, scroll, virtual_stack, Decorators, VirtualStackDirection,
VirtualStackItemSize,
container, h_stack, label, scroll, virtual_stack, Decorators, VirtualDirection,
VirtualItemSize,
},
EventPropagation,
};
Expand All @@ -21,8 +21,8 @@ pub fn draggable_sidebar_view() -> impl View {

let side_bar = scroll({
virtual_stack(
VirtualStackDirection::Vertical,
VirtualStackItemSize::Fixed(Box::new(|| 22.0)),
VirtualDirection::Vertical,
VirtualItemSize::Fixed(Box::new(|| 22.0)),
move || long_list.get(),
move |item| *item,
move |item| {
Expand Down
12 changes: 6 additions & 6 deletions examples/layout/src/holy_grail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use floem::{
style::Position,
view::View,
views::{
container, h_stack, label, scroll, v_stack, virtual_stack, Decorators,
VirtualStackDirection, VirtualStackItemSize,
container, h_stack, label, scroll, v_stack, virtual_stack, Decorators, VirtualDirection,
VirtualItemSize,
},
};

Expand All @@ -22,8 +22,8 @@ pub fn holy_grail_view() -> impl View {

let side_bar_right = scroll({
virtual_stack(
VirtualStackDirection::Vertical,
VirtualStackItemSize::Fixed(Box::new(|| 22.0)),
VirtualDirection::Vertical,
VirtualItemSize::Fixed(Box::new(|| 22.0)),
move || long_list.get(),
move |item| *item,
move |item| {
Expand All @@ -49,8 +49,8 @@ pub fn holy_grail_view() -> impl View {

let side_bar_left = scroll({
virtual_stack(
VirtualStackDirection::Vertical,
VirtualStackItemSize::Fixed(Box::new(|| 22.0)),
VirtualDirection::Vertical,
VirtualItemSize::Fixed(Box::new(|| 22.0)),
move || long_list.get(),
move |item| *item,
move |item| {
Expand Down
8 changes: 4 additions & 4 deletions examples/layout/src/left_sidebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use floem::{
style::Position,
view::View,
views::{
container, h_stack, label, scroll, v_stack, virtual_stack, Decorators,
VirtualStackDirection, VirtualStackItemSize,
container, h_stack, label, scroll, v_stack, virtual_stack, Decorators, VirtualDirection,
VirtualItemSize,
},
};

Expand All @@ -22,8 +22,8 @@ pub fn left_sidebar_view() -> impl View {

let side_bar = scroll({
virtual_stack(
VirtualStackDirection::Vertical,
VirtualStackItemSize::Fixed(Box::new(|| 22.0)),
VirtualDirection::Vertical,
VirtualItemSize::Fixed(Box::new(|| 22.0)),
move || long_list.get(),
move |item| *item,
move |item| {
Expand Down
8 changes: 4 additions & 4 deletions examples/layout/src/right_sidebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use floem::{
style::Position,
view::View,
views::{
container, h_stack, label, scroll, v_stack, virtual_stack, Decorators,
VirtualStackDirection, VirtualStackItemSize,
container, h_stack, label, scroll, v_stack, virtual_stack, Decorators, VirtualDirection,
VirtualItemSize,
},
};

Expand All @@ -22,8 +22,8 @@ pub fn right_sidebar_view() -> impl View {

let side_bar = scroll({
virtual_stack(
VirtualStackDirection::Vertical,
VirtualStackItemSize::Fixed(Box::new(|| 22.0)),
VirtualDirection::Vertical,
VirtualItemSize::Fixed(Box::new(|| 22.0)),
move || long_list.get(),
move |item| *item,
move |item| {
Expand Down
6 changes: 3 additions & 3 deletions examples/virtual_list/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use floem::{
view::View,
views::virtual_stack,
views::Decorators,
views::{container, label, scroll, VirtualStackDirection, VirtualStackItemSize},
views::{container, label, scroll, VirtualDirection, VirtualItemSize},
};

fn app_view() -> impl View {
Expand All @@ -14,8 +14,8 @@ fn app_view() -> impl View {
container(
scroll(
virtual_stack(
VirtualStackDirection::Vertical,
VirtualStackItemSize::Fixed(Box::new(|| 20.0)),
VirtualDirection::Vertical,
VirtualItemSize::Fixed(Box::new(|| 20.0)),
move || long_list.get(),
move |item| *item,
move |item| label(move || item.to_string()).style(|s| s.height(20.0)),
Expand Down
70 changes: 14 additions & 56 deletions examples/widget-gallery/src/lists.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
use floem::{
cosmic_text::Weight,
event::{Event, EventListener},
keyboard::{Key, NamedKey},
peniko::Color,
reactive::create_signal,
style::{CursorStyle, JustifyContent},
style::JustifyContent,
view::View,
views::{
container, label, scroll, stack, virtual_stack, Decorators, VirtualStackDirection,
VirtualStackItemSize,
container, label, scroll, stack, Decorators, VirtualDirection, VirtualItemSize,
VirtualVector,
},
widgets::{checkbox, list},
EventPropagation,
widgets::{checkbox, list, virtual_list},
};

use crate::form::{form, form_item};
Expand All @@ -37,21 +34,15 @@ fn enhanced_list() -> impl View {
let long_list: im::Vector<i32> = (0..100).collect();
let (long_list, set_long_list) = create_signal(long_list);

let (selected, set_selected) = create_signal(0);
let list_width = 180.0;
let item_height = 32.0;
scroll(
virtual_stack(
VirtualStackDirection::Vertical,
VirtualStackItemSize::Fixed(Box::new(|| 32.0)),
move || long_list.get(),
move |item| *item,
move |item| {
let index = long_list
.get_untracked()
.iter()
.position(|it| *it == item)
.unwrap();
virtual_list(
VirtualDirection::Vertical,
VirtualItemSize::Fixed(Box::new(|| 32.0)),
move || long_list.get().enumerate(),
move |(_, item)| *item,
move |(index, item)| {
let (is_checked, set_is_checked) = create_signal(true);
container({
stack({
Expand Down Expand Up @@ -87,45 +78,12 @@ fn enhanced_list() -> impl View {
}),
)
})
.style(move |s| s.height(item_height).width_full().items_center())
.style(move |s| s.height_full().width_full().items_center())
})
.on_click_stop(move |_| {
set_selected.update(|v: &mut usize| {
*v = long_list.get().iter().position(|it| *it == item).unwrap();
});
})
.on_event(EventListener::KeyDown, move |e| {
if let Event::KeyDown(key_event) = e {
let sel = selected.get();
match key_event.key.logical_key {
Key::Named(NamedKey::ArrowUp) => {
if sel > 0 {
set_selected.update(|v| *v -= 1);
}
EventPropagation::Stop
}
Key::Named(NamedKey::ArrowDown) => {
if sel < long_list.get().len() - 1 {
set_selected.update(|v| *v += 1);
}
EventPropagation::Stop
}
_ => EventPropagation::Continue,
}
} else {
EventPropagation::Continue
}
})
.keyboard_navigatable()
.style(move |s| {
s.flex_row()
.height(item_height)
.apply_if(index == selected.get(), |s| s.background(Color::GRAY))
.apply_if(index != 0, |s| {
s.border_top(1.0).border_color(Color::LIGHT_GRAY)
})
.focus_visible(|s| s.border(2.).border_color(Color::BLUE))
.hover(|s| s.background(Color::LIGHT_GRAY).cursor(CursorStyle::Pointer))
s.flex_row().height(item_height).apply_if(index != 0, |s| {
s.border_top(1.0).border_color(Color::LIGHT_GRAY)
})
})
},
)
Expand Down
6 changes: 3 additions & 3 deletions examples/widget-gallery/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use floem::{
view::View,
views::{
container, container_box, h_stack, label, scroll, stack, tab, v_stack, virtual_stack,
Decorators, VirtualStackDirection, VirtualStackItemSize,
Decorators, VirtualDirection, VirtualItemSize,
},
widgets::button,
EventPropagation,
Expand All @@ -45,8 +45,8 @@ fn app_view() -> impl View {

let list = scroll({
virtual_stack(
VirtualStackDirection::Vertical,
VirtualStackItemSize::Fixed(Box::new(|| 36.0)),
VirtualDirection::Vertical,
VirtualItemSize::Fixed(Box::new(|| 36.0)),
move || tabs.get(),
move |item| *item,
move |item| {
Expand Down
1 change: 1 addition & 0 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1238,6 +1238,7 @@ impl<'a> ComputeLayoutCx<'a> {
.get_mut(&id)
.and_then(|s| s.move_listener.as_mut())
}

/// Internal method used by Floem. This method derives its calculations based on the [Taffy Node](taffy::prelude::Node) returned by the `View::layout` method.
///
/// It's responsible for:
Expand Down
6 changes: 3 additions & 3 deletions src/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

use std::{any::Any, cell::RefCell, collections::HashMap, sync::atomic::AtomicU64};

use kurbo::Point;
use kurbo::{Point, Rect};

use crate::{
animate::Animation,
Expand Down Expand Up @@ -217,8 +217,8 @@ impl Id {
self.add_update_message(UpdateMessage::PopoutMenu { id: *self, menu });
}

pub fn scroll_to(&self) {
self.add_update_message(UpdateMessage::ScrollTo { id: *self });
pub fn scroll_to(&self, rect: Option<Rect>) {
self.add_update_message(UpdateMessage::ScrollTo { id: *self, rect });
}

pub fn inspect(&self) {
Expand Down
3 changes: 2 additions & 1 deletion src/update.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{any::Any, cell::RefCell, collections::HashMap};

use kurbo::{Point, Size, Vec2};
use kurbo::{Point, Rect, Size, Vec2};
use winit::window::ResizeDirection;

use crate::{
Expand Down Expand Up @@ -124,6 +124,7 @@ pub(crate) enum UpdateMessage {
Inspect,
ScrollTo {
id: Id,
rect: Option<Rect>,
},
FocusWindow,
SetImeAllowed {
Expand Down
8 changes: 4 additions & 4 deletions src/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,13 +235,13 @@ pub trait View {

/// Scrolls the view and all direct and indirect children to bring the `target` view to be
/// visible. Returns true if this view contains or is the target.
fn scroll_to(&mut self, cx: &mut AppState, target: Id) -> bool {
fn scroll_to(&mut self, cx: &mut AppState, target: Id, rect: Option<Rect>) -> bool {
if self.id() == target {
return true;
}
let mut found = false;
self.for_each_child_mut(&mut |child| {
found |= child.scroll_to(cx, target);
found |= child.scroll_to(cx, target, rect);
found
});
found
Expand Down Expand Up @@ -700,7 +700,7 @@ impl View for Box<dyn View> {
(**self).paint(cx)
}

fn scroll_to(&mut self, cx: &mut AppState, target: Id) -> bool {
(**self).scroll_to(cx, target)
fn scroll_to(&mut self, cx: &mut AppState, target: Id, rect: Option<Rect>) -> bool {
(**self).scroll_to(cx, target, rect)
}
}
12 changes: 6 additions & 6 deletions src/views/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ enum ListUpdate {
ScrollToSelected,
}

struct Item {
data: ViewData,
index: usize,
selection: RwSignal<Option<usize>>,
child: Box<dyn View>,
pub(crate) struct Item {
pub(crate) data: ViewData,
pub(crate) index: usize,
pub(crate) selection: RwSignal<Option<usize>>,
pub(crate) child: Box<dyn View>,
}

pub struct List {
Expand Down Expand Up @@ -171,7 +171,7 @@ impl View for List {
}
ListUpdate::ScrollToSelected => {
if let Some(index) = self.selection.get_untracked() {
self.child.children[index].id().scroll_to();
self.child.children[index].id().scroll_to(None);
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/views/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ pub use decorator::*;
mod list;
pub use list::*;

mod virtual_list;
pub use virtual_list::*;

mod virtual_stack;
pub use virtual_stack::*;

Expand Down
28 changes: 22 additions & 6 deletions src/views/scroll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,9 +580,25 @@ impl Scroll {
}
}

fn do_scroll_to_view(&mut self, app_state: &mut AppState, target: Id) {
fn do_scroll_to_view(
&mut self,
app_state: &mut AppState,
target: Id,
target_rect: Option<Rect>,
) {
if app_state.get_layout(target).is_some() && !app_state.is_hidden_recursive(target) {
let rect = app_state.get_layout_rect(target);
let mut rect = app_state.get_layout_rect(target);

if let Some(target_rect) = target_rect {
rect = rect + target_rect.origin().to_vec2();

let new_size = target_rect
.size()
.to_rect()
.intersect(rect.size().to_rect())
.size();
rect = rect.with_size(new_size);
}

// `get_layout_rect` is window-relative so we have to
// convert it to child view relative.
Expand Down Expand Up @@ -651,7 +667,7 @@ impl View for Scroll {
self.scroll_to(cx.app_state, point);
}
ScrollState::ScrollToView(id) => {
self.do_scroll_to_view(cx.app_state, id);
self.do_scroll_to_view(cx.app_state, id, None);
}
ScrollState::HiddenBar(hide) => {
self.hide = hide;
Expand All @@ -667,10 +683,10 @@ impl View for Scroll {
}
}

fn scroll_to(&mut self, cx: &mut AppState, target: Id) -> bool {
let found = self.child.scroll_to(cx, target);
fn scroll_to(&mut self, cx: &mut AppState, target: Id, rect: Option<Rect>) -> bool {
let found = self.child.scroll_to(cx, target, rect);
if found {
self.do_scroll_to_view(cx, target);
self.do_scroll_to_view(cx, target, rect);
}
found
}
Expand Down
Loading