Skip to content

Commit

Permalink
Allow tab to have no active tabs.
Browse files Browse the repository at this point in the history
* this is a common scenario when using a tabbed interface with one-tab per document without any documents having yet been loaded.
  • Loading branch information
hydra committed Sep 26, 2024
1 parent b9bcd24 commit 859a941
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 22 deletions.
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);
}
}
}
}

0 comments on commit 859a941

Please sign in to comment.