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

Allow tab to have no active tabs. #592

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion examples/layout/src/tab_navigation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pub fn tab_navigation_view() -> impl IntoView {
let main_content = container(
scroll(
tab(
move || active_tab.get(),
move || Some(active_tab.get()),
move || tabs.get(),
|it| *it,
|it| container(label(move || format!("{}", it))),
Expand Down
2 changes: 1 addition & 1 deletion examples/widget-gallery/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ fn app_view() -> impl IntoView {
let left = v_stack((list, inspector)).style(|s| s.height_full().column_gap(5.0));

let tab = tab(
move || active_tab.get(),
move || Some(active_tab.get()),
move || tabs.get(),
|it| *it,
|it| match it {
Expand Down
2 changes: 1 addition & 1 deletion src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1111,7 +1111,7 @@ pub fn capture(window_id: WindowId) {
.style(|s| s.background(Color::WHITE));

let tab = tab(
move || selected.get(),
move || Some(selected.get()),
move || [0, 1].into_iter(),
|it| *it,
move |it| match it {
Expand Down
57 changes: 36 additions & 21 deletions src/views/tab.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::{hash::Hash, marker::PhantomData};

use floem_reactive::{as_child_of_current_scope, create_effect, Scope};
use smallvec::SmallVec;
use taffy::style::Display;
Expand All @@ -18,21 +17,22 @@ type ViewFn<T> = Box<dyn Fn(T) -> (Box<dyn View>, Scope)>;
enum TabState<V> {
Diff(Box<Diff<V>>),
Active(usize),
None
}

pub struct Tab<T>
where
T: 'static,
{
id: ViewId,
active: usize,
active: Option<usize>,
children: Vec<Option<(ViewId, Scope)>>,
view_fn: ViewFn<T>,
phatom: PhantomData<T>,
}

pub fn tab<IF, I, T, KF, K, VF, V>(
active_fn: impl Fn() -> usize + 'static,
active_fn: impl Fn() -> Option<usize> + 'static,
each_fn: IF,
key_fn: KF,
view_fn: VF,
Expand Down Expand Up @@ -72,20 +72,23 @@ where
}
diff
};
id.update_state(TabState::Diff(Box::new(diff)));
id.update_state(TabState::<T>::Diff(Box::new(diff)));
HashRun(hashed_items)
});

create_effect(move |_| {
let active = active_fn();
id.update_state(TabState::Active::<T>(active));
let active_key = active_fn();
match active_key {
Some(key) => id.update_state(TabState::Active::<T>(key)),
None => id.update_state(TabState::None::<T>),
}
});

let view_fn = Box::new(as_child_of_current_scope(move |e| view_fn(e).into_any()));

Tab {
id,
active: 0,
active: None,
children: Vec::new(),
view_fn,
phatom: PhantomData,
Expand All @@ -98,7 +101,7 @@ impl<T> View for Tab<T> {
}

fn debug_name(&self) -> std::borrow::Cow<'static, str> {
format!("Tab: {}", self.active).into()
format!("Tab: {:?}", self.active).into()
}

fn update(&mut self, cx: &mut UpdateCx, state: Box<dyn std::any::Any>) {
Expand All @@ -114,7 +117,10 @@ impl<T> View for Tab<T> {
);
}
TabState::Active(active) => {
self.active = active;
self.active.replace(active);
}
TabState::None => {
self.active.take();
}
}
self.id.request_all();
Expand All @@ -131,23 +137,32 @@ impl<T> View for Tab<T> {
let mut child_view = child_view.borrow_mut();
child_view.combined_style = child_view.combined_style.clone().set(
DisplayProp,
if i != self.active {
// set display to none for non active child
Display::None
} else {
Display::Flex
},

match self.active {
None => {
Display::None
}
Some(active_index) if active_index == i => {
Display::Flex
}
Some(_active_index) => {
// set display to none for non-active child
Display::None
}
}
);
}
}

fn paint(&mut self, cx: &mut crate::context::PaintCx) {
if let Some(Some((active, _))) = self
.children
.get(self.active)
.or_else(|| self.children.first())
{
cx.paint_view(*active);
if let Some(active_index) = self.active {
if let Some(Some((active, _))) = self
.children
.get(active_index)
.or_else(|| self.children.first())
{
cx.paint_view(*active);
}
}
}
}
Loading