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

TabBar/Tabs using a type instead of usize for active_tab #128

Merged
merged 9 commits into from
Jun 5, 2023
10 changes: 8 additions & 2 deletions examples/tab_bar/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ impl Sandbox for TabBarExample {

fn update(&mut self, message: Message) {
match message {
Message::TabSelected(index) => self.active_tab = index,
Message::TabSelected(index) => {
println!("Tab selected: {}", index);
self.active_tab = index
},
Message::TabClosed(index) => {
self.tabs.remove(index);
println!("active tab before: {}", self.active_tab);
Expand Down Expand Up @@ -97,7 +100,10 @@ impl Sandbox for TabBarExample {
.fold(
TabBar::new(self.active_tab, Message::TabSelected),
|tab_bar, (tab_label, _)| {
tab_bar.push(TabLabel::Text(tab_label.to_owned()))
// manually create a new index for the new tab
// starting from 0, when there is no tab created yet
let new_idx = tab_bar.get_tab_count();
tab_bar.push(new_idx, TabLabel::Text(tab_label.to_owned()))
},
)
.on_close(Message::TabClosed)
Expand Down
23 changes: 15 additions & 8 deletions examples/tabs/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,23 @@ fn main() -> iced::Result {
}

struct TabBarExample {
active_tab: usize,
active_tab: TabId,
login_tab: LoginTab,
ferris_tab: FerrisTab,
counter_tab: CounterTab,
settings_tab: SettingsTab,
}
#[derive(Clone, PartialEq, Eq, Debug)]
enum TabId {
Login,
Ferris,
Counter,
Settings,
}

#[derive(Clone, Debug)]
enum Message {
TabSelected(usize),
TabSelected(TabId),
Login(LoginMessage),
Ferris(FerrisMessage),
Counter(CounterMessage),
Expand All @@ -68,7 +75,7 @@ impl Sandbox for TabBarExample {

fn new() -> Self {
TabBarExample {
active_tab: 0,
active_tab: TabId::Login,
login_tab: LoginTab::new(),
ferris_tab: FerrisTab::new(),
counter_tab: CounterTab::new(),
Expand Down Expand Up @@ -102,11 +109,11 @@ impl Sandbox for TabBarExample {
.tab_bar_theme
.unwrap_or_default();

Tabs::new(self.active_tab, Message::TabSelected)
.push(self.login_tab.tab_label(), self.login_tab.view())
.push(self.ferris_tab.tab_label(), self.ferris_tab.view())
.push(self.counter_tab.tab_label(), self.counter_tab.view())
.push(self.settings_tab.tab_label(), self.settings_tab.view())
Tabs::new(self.active_tab.clone(), Message::TabSelected)
.push(TabId::Login, self.login_tab.tab_label(), self.login_tab.view())
.push(TabId::Ferris, self.ferris_tab.tab_label(), self.ferris_tab.view())
.push(TabId::Counter, self.counter_tab.tab_label(), self.counter_tab.view())
.push(TabId::Settings, self.settings_tab.tab_label(), self.settings_tab.view())
.tab_bar_style(theme)
.icon_font(ICON_FONT)
.tab_bar_position(match position {
Expand Down
2 changes: 1 addition & 1 deletion src/graphics/tab_bar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ pub use tab_bar::tab_label::TabLabel;
/// A tab bar to show tabs.
///
/// This is an alias of an `iced_native` `TabBar` with an `iced_wgpu::Renderer`.
pub type TabBar<Message, Backend, Theme> = tab_bar::TabBar<Message, Renderer<Backend, Theme>>;
pub type TabBar<Message, TabId, Backend, Theme> = tab_bar::TabBar<Message, TabId, Renderer<Backend, Theme>>;
2 changes: 1 addition & 1 deletion src/graphics/tabs.rs
genusistimelord marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ pub use tabs::tab_bar_position::TabBarPosition;
///
/// This is an alias of an `iced_native` Tabs widget with an
/// `iced_wgpu::Renderer`.
pub type Tabs<'a, Message, Backend, Theme> = tabs::Tabs<'a, Message, Renderer<Backend, Theme>>;
pub type Tabs<'a, Message, TabId, Backend, Theme> = tabs::Tabs<'a, Message, TabId, Renderer<Backend, Theme>>;
79 changes: 52 additions & 27 deletions src/native/tab_bar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,36 +41,44 @@ const DEFAULT_SPACING: f32 = 0.0;
/// # use iced_native::{renderer::Null};
/// # use iced_aw::native::tab_bar;
/// #
/// # pub type TabBar<Message> = tab_bar::TabBar<Message, Null>;
/// # pub type TabBar<Message> = tab_bar::TabBar<Message, u32, Null>;
andretietz marked this conversation as resolved.
Show resolved Hide resolved
/// #[derive(Debug, Clone)]
/// enum Message {
/// TabSelected(usize),
/// TabSelected(TabId),
/// }
///
/// let active_tab = 0;
/// #[derive(PartialEq, Hash)]
/// enum TabId {
/// One,
/// Two,
/// Three,
/// }
///
/// let tab_bar = TabBar::new(
/// active_tab,
/// TabId::One,
/// Message::TabSelected,
/// )
/// .push(TabLabel::Text(String::from("One")))
/// .push(TabLabel::Text(String::from("Two")))
/// .push(TabLabel::Text(String::from("Three")));
/// .push(TabId::One, TabLabel::Text(String::from("One")))
/// .push(TabId::Two, TabLabel::Text(String::from("Two")))
/// .push(TabId::Three, TabLabel::Text(String::from("Three")));
/// ```
#[allow(missing_debug_implementations)]
pub struct TabBar<Message, Renderer>
pub struct TabBar<Message, TabId, Renderer>
where
Renderer: iced_native::Renderer + iced_native::text::Renderer,
Renderer::Theme: StyleSheet,
TabId: Eq + Clone
{
/// The currently active tab.
/// The index and identifier of the currently active tab.
andretietz marked this conversation as resolved.
Show resolved Hide resolved
active_tab: usize,
/// The vector containing the labels of the tabs.
tab_labels: Vec<TabLabel>,
/// The vector containing the indices of the tabs.
tab_indices: Vec<TabId>,
/// The function that produces the message when a tab is selected.
on_select: Box<dyn Fn(usize) -> Message>,
on_select: Box<dyn Fn(TabId) -> Message>,
/// The function that produces the message when the close icon was pressed.
on_close: Option<Box<dyn Fn(usize) -> Message>>,
on_close: Option<Box<dyn Fn(TabId) -> Message>>,
/// The width of the [`TabBar`](TabBar).
width: Length,
/// The width of the tabs of the [`TabBar`](TabBar).
Expand Down Expand Up @@ -99,10 +107,11 @@ where
_renderer: PhantomData<Renderer>,
}

impl<Message, Renderer> TabBar<Message, Renderer>
impl<Message, TabId, Renderer> TabBar<Message, TabId, Renderer>
where
Renderer: iced_native::Renderer + iced_native::text::Renderer<Font = iced_native::Font>,
Renderer::Theme: StyleSheet,
TabId: Eq + Clone
{
/// Creates a new [`TabBar`](TabBar) with the index of the selected tab and a
/// specified message which will be send when a tab is selected by the user.
Expand All @@ -111,9 +120,9 @@ where
/// * the index of the currently active tab.
/// * the function that will be called if a tab is selected by the user.
/// It takes the index of the selected tab.
pub fn new<F>(active_tab: usize, on_select: F) -> Self
pub fn new<F>(active_tab: TabId, on_select: F) -> Self
where
F: 'static + Fn(usize) -> Message,
F: 'static + Fn(TabId) -> Message,
{
Self::width_tab_labels(active_tab, Vec::new(), on_select)
}
Expand All @@ -126,13 +135,14 @@ where
/// * a vector containing the [`TabLabel`](TabLabel)s of the [`TabBar`](TabBar).
/// * the function that will be called if a tab is selected by the user.
/// It takes the index of the selected tab.
pub fn width_tab_labels<F>(active_tab: usize, tab_labels: Vec<TabLabel>, on_select: F) -> Self
pub fn width_tab_labels<F>(active_tab: TabId, tab_labels: Vec<(TabId, TabLabel)>, on_select: F) -> Self
andretietz marked this conversation as resolved.
Show resolved Hide resolved
where
F: 'static + Fn(usize) -> Message,
F: 'static + Fn(TabId) -> Message,
{
Self {
active_tab,
tab_labels,
active_tab: tab_labels.iter().position(|(id, _)| *id == active_tab).unwrap_or(0),
tab_indices: tab_labels.iter().map(|(id, _)| id.clone()).collect(),
tab_labels: tab_labels.into_iter().map(|(_, label)| label).collect(),
on_select: Box::new(on_select),
on_close: None,
width: Length::Fill,
Expand All @@ -153,18 +163,30 @@ where

/// Gets the index of the currently active tab on the [`TabBar`](TabBar).
#[must_use]
pub fn get_active_tab(&self) -> usize {
pub fn get_active_tab_idx(&self) -> usize {
self.active_tab
}

/// Gets the id of the currently active tab on the [`TabBar`](TabBar).
#[must_use]
pub fn get_active_tab_id(&self) -> &TabId {
self.tab_indices.get(self.active_tab).unwrap()
}

/// Gets the amount of tabs on the [`TabBar`](TabBar).
#[must_use]
pub fn get_tab_count(&self) -> usize {
self.tab_indices.len()
}

/// Sets the message that will be produced when the close icon of a tab
/// on the [`TabBar`](TabBar) is pressed.
///
/// Setting this enables the drawing of a close icon on the tabs.
#[must_use]
pub fn on_close<F>(mut self, on_close: F) -> Self
where
F: 'static + Fn(usize) -> Message,
F: 'static + Fn(TabId) -> Message,
{
self.on_close = Some(Box::new(on_close));
self
Expand Down Expand Up @@ -273,16 +295,18 @@ where

/// Pushes a [`TabLabel`](crate::tab_bar::TabLabel) to the [`TabBar`](TabBar).
#[must_use]
pub fn push(mut self, tab_label: TabLabel) -> Self {
pub fn push(mut self, id: TabId, tab_label: TabLabel) -> Self {
self.tab_labels.push(tab_label);
self.tab_indices.push(id);
self
}
}

impl<Message, Renderer> Widget<Message, Renderer> for TabBar<Message, Renderer>
impl<Message, TabId, Renderer> Widget<Message, Renderer> for TabBar<Message, TabId, Renderer>
where
Renderer: iced_native::Renderer + iced_native::text::Renderer<Font = iced_native::Font>,
Renderer::Theme: StyleSheet + iced_style::text::StyleSheet,
TabId: Eq + Clone
{
fn width(&self) -> Length {
self.width
Expand Down Expand Up @@ -370,8 +394,8 @@ where
cross_layout.bounds().contains(cursor_position)
})
.map_or_else(
|| (self.on_select)(new_selected),
|on_close| (on_close)(new_selected),
|| (self.on_select)(self.tab_indices[new_selected].clone()),
|on_close| (on_close)(self.tab_indices[new_selected].clone()),
),
);
return event::Status::Captured;
Expand Down Expand Up @@ -448,7 +472,7 @@ where
layout,
theme,
self.style,
i == self.active_tab,
i == self.get_active_tab_idx(),
cursor_position,
self.icon_font.unwrap_or(icons::ICON_FONT),
self.text_font.unwrap_or_default(),
Expand Down Expand Up @@ -611,13 +635,14 @@ fn draw_tab<Renderer>(
};
}

impl<'a, Message, Renderer> From<TabBar<Message, Renderer>> for Element<'a, Message, Renderer>
impl<'a, Message, TabId, Renderer> From<TabBar<Message, TabId, Renderer>> for Element<'a, Message, Renderer>
where
Renderer: 'a + iced_native::Renderer + iced_native::text::Renderer<Font = iced_native::Font>,
Renderer::Theme: StyleSheet + iced_style::text::StyleSheet,
Message: 'a,
TabId: 'a + Eq + Clone
{
fn from(tab_bar: TabBar<Message, Renderer>) -> Self {
fn from(tab_bar: TabBar<Message, TabId, Renderer>) -> Self {
Element::new(tab_bar)
}
}
Loading