Skip to content

Commit

Permalink
Add list with selections, selected style selectors and scroll_to
Browse files Browse the repository at this point in the history
  • Loading branch information
Zoxc committed Jan 2, 2024
1 parent 4eeef28 commit 13758c4
Show file tree
Hide file tree
Showing 13 changed files with 369 additions and 42 deletions.
14 changes: 3 additions & 11 deletions examples/widget-gallery/src/lists.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use floem::{
container, label, scroll, stack, virtual_stack, Decorators, VirtualStackDirection,
VirtualStackItemSize,
},
widgets::checkbox,
widgets::{checkbox, list},
EventPropagation,
};

Expand All @@ -26,17 +26,9 @@ pub fn virt_list_view() -> impl View {
}

fn simple_list() -> impl View {
let long_list: im::Vector<i32> = (0..100).collect();
let (long_list, _set_long_list) = create_signal(long_list);
scroll(
virtual_stack(
VirtualStackDirection::Vertical,
VirtualStackItemSize::Fixed(Box::new(|| 20.0)),
move || long_list.get(),
move |item| *item,
move |item| label(move || item.to_string()).style(|s| s.height(24.0)),
)
.style(|s| s.flex_col()),
list((0..100).map(|i| label(move || i.to_string()).style(|s| s.height(24.0))))
.style(|s| s.width_full()),
)
.style(|s| s.width(100.0).height(300.0).border(1.0))
}
Expand Down
37 changes: 25 additions & 12 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,16 +255,6 @@ impl AppState {
.unwrap_or(false)
}

pub fn get_interact_state(&self, id: &Id) -> InteractionState {
InteractionState {
is_hovered: self.is_hovered(id),
is_disabled: self.is_disabled(id),
is_focused: self.is_focused(id),
is_clicking: self.is_clicking(id),
using_keyboard_navigation: self.keyboard_navigation,
}
}

pub fn set_root_size(&mut self, size: Size) {
self.root_size = size;
self.compute_layout();
Expand Down Expand Up @@ -316,7 +306,7 @@ impl AppState {
}

/// Requests style for a view and all direct and indirect children.
pub(crate) fn request_style_recursive(&mut self, id: Id) {
pub fn request_style_recursive(&mut self, id: Id) {
let view = self.view_state(id);
view.request_style_recursive = true;
self.request_style(id);
Expand Down Expand Up @@ -999,6 +989,7 @@ impl<'a> EventCx<'a> {
#[derive(Default)]
pub struct InteractionState {
pub(crate) is_hovered: bool,
pub(crate) is_selected: bool,
pub(crate) is_disabled: bool,
pub(crate) is_focused: bool,
pub(crate) is_clicking: bool,
Expand All @@ -1013,7 +1004,9 @@ pub struct StyleCx<'a> {
saved: Vec<Rc<Style>>,
pub(crate) now: Instant,
saved_disabled: Vec<bool>,
saved_selected: Vec<bool>,
disabled: bool,
selected: bool,
}

impl<'a> StyleCx<'a> {
Expand All @@ -1026,7 +1019,25 @@ impl<'a> StyleCx<'a> {
saved: Default::default(),
now: Instant::now(),
saved_disabled: Default::default(),
saved_selected: Default::default(),
disabled: false,
selected: false,
}
}

/// Marks the current context as selected.
pub fn selected(&mut self) {
self.selected = true;
}

fn get_interact_state(&self, id: &Id) -> InteractionState {
InteractionState {
is_selected: self.selected,
is_hovered: self.app_state.is_hovered(id),
is_disabled: self.app_state.is_disabled(id),
is_focused: self.app_state.is_focused(id),
is_clicking: self.app_state.is_clicking(id),
using_keyboard_navigation: self.app_state.keyboard_navigation,
}
}

Expand Down Expand Up @@ -1062,7 +1073,7 @@ impl<'a> StyleCx<'a> {
});
}

let mut view_interact_state = self.app_state.get_interact_state(&id);
let mut view_interact_state = self.get_interact_state(&id);
view_interact_state.is_disabled |= self.disabled;
self.disabled = view_interact_state.is_disabled;
let mut new_frame = self.app_state.compute_style(
Expand Down Expand Up @@ -1124,11 +1135,13 @@ impl<'a> StyleCx<'a> {
pub fn save(&mut self) {
self.saved.push(self.current.clone());
self.saved_disabled.push(self.disabled);
self.saved_selected.push(self.selected);
}

pub fn restore(&mut self) {
self.current = self.saved.pop().unwrap_or_default();
self.disabled = self.saved_disabled.pop().unwrap_or_default();
self.selected = self.saved_selected.pop().unwrap_or_default();
}

pub fn get_prop<P: StyleProp>(&self, _prop: P) -> Option<P::Type> {
Expand Down
4 changes: 4 additions & 0 deletions src/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ 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 inspect(&self) {
self.add_update_message(UpdateMessage::Inspect);
}
Expand Down
11 changes: 11 additions & 0 deletions src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,12 @@ impl Style {
self.apply_mut(map);
}
}
if interact_state.is_selected {
if let Some(mut map) = self.selectors.remove(&StyleSelector::Selected) {
map.apply_interact_state(interact_state, screen_size_bp);
self.apply_mut(map);
}
}
if interact_state.is_disabled {
if let Some(mut map) = self.selectors.remove(&StyleSelector::Disabled) {
map.apply_interact_state(interact_state, screen_size_bp);
Expand Down Expand Up @@ -850,6 +856,7 @@ pub enum StyleSelector {
Disabled,
Active,
Dragging,
Selected,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Default)]
Expand Down Expand Up @@ -1154,6 +1161,10 @@ impl Style {
self.selector(StyleSelector::FocusVisible, style)
}

pub fn selected(self, style: impl FnOnce(Style) -> Style) -> Self {
self.selector(StyleSelector::Selected, style)
}

pub fn disabled(self, style: impl FnOnce(Style) -> Style) -> Self {
self.selector(StyleSelector::Disabled, style)
}
Expand Down
3 changes: 3 additions & 0 deletions src/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ pub(crate) enum UpdateMessage {
id: Id,
},
Inspect,
ScrollTo {
id: Id,
},
FocusWindow,
SetImeAllowed {
allowed: bool,
Expand Down
18 changes: 18 additions & 0 deletions src/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,20 @@ pub trait View {
false
});
}

/// 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 {
if self.id() == target {
return true;
}
let mut found = false;
self.for_each_child_mut(&mut |child| {
found |= child.scroll_to(cx, target);
found
});
found
}
}

/// Computes the layout of the view's children, if any.
Expand Down Expand Up @@ -685,4 +699,8 @@ impl View for Box<dyn View> {
fn paint(&mut self, cx: &mut PaintCx) {
(**self).paint(cx)
}

fn scroll_to(&mut self, cx: &mut AppState, target: Id) -> bool {
(**self).scroll_to(cx, target)
}
}
Loading

0 comments on commit 13758c4

Please sign in to comment.