Skip to content

Commit 5784ec4

Browse files
committed
Update tabs/tab_bar to iced 0.14
1 parent fe5fe17 commit 5784ec4

8 files changed

Lines changed: 108 additions & 104 deletions

File tree

examples/tab_bar.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@ use iced::{
66
widget::{Button, Column, Row, Text, TextInput},
77
Alignment, Element, Length,
88
};
9+
10+
use iced_aw::ICED_AW_FONT_BYTES;
911
use iced_aw::{TabBar, TabLabel};
1012

1113
fn main() -> iced::Result {
1214
iced::application(
13-
"Tab Bar example",
15+
TabBarExample::default,
1416
TabBarExample::update,
1517
TabBarExample::view,
1618
)
17-
.font(iced_fonts::REQUIRED_FONT_BYTES)
19+
.font(ICED_AW_FONT_BYTES)
1820
.run()
1921
}
2022

examples/tabs/counter.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@ pub struct CounterTab {
1818
}
1919

2020
impl CounterTab {
21-
pub fn new() -> Self {
22-
CounterTab { value: 0 }
23-
}
24-
2521
pub fn update(&mut self, message: CounterMessage) {
2622
match message {
2723
CounterMessage::Increase => self.value += 1,

examples/tabs/ferris.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,6 @@ pub struct FerrisTab {
1818
}
1919

2020
impl FerrisTab {
21-
pub fn new() -> Self {
22-
FerrisTab {
23-
ferris_width: 100.0,
24-
}
25-
}
26-
2721
pub fn update(&mut self, message: FerrisMessage) {
2822
match message {
2923
FerrisMessage::ImageWidthChanged(value) => self.ferris_width = value,

examples/tabs/login.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,6 @@ pub struct LoginTab {
2222
}
2323

2424
impl LoginTab {
25-
pub fn new() -> Self {
26-
LoginTab {
27-
username: String::new(),
28-
password: String::new(),
29-
}
30-
}
31-
3225
pub fn update(&mut self, message: LoginMessage) {
3326
match message {
3427
LoginMessage::UsernameChanged(value) => self.username = value,

examples/tabs/main.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use iced::{
88
widget::{Column, Container, Text},
99
Element, Font, Length,
1010
};
11+
use iced_aw::ICED_AW_FONT_BYTES;
1112
use iced_aw::{TabLabel, Tabs};
1213
use login::{LoginMessage, LoginTab};
1314

@@ -20,7 +21,7 @@ use counter::{CounterMessage, CounterTab};
2021
mod settings;
2122
use settings::{style_from_index, SettingsMessage, SettingsTab, TabBarPosition};
2223

23-
const HEADER_SIZE: u16 = 32;
24+
const HEADER_SIZE: u32 = 32;
2425
const TAB_PADDING: u16 = 16;
2526
const ICON_BYTES: &[u8] = include_bytes!("./fonts/icons.ttf");
2627
const ICON: Font = Font::with_name("icons");
@@ -44,10 +45,14 @@ impl From<Icon> for char {
4445
}
4546

4647
fn main() -> iced::Result {
47-
iced::application("Tabs example", TabBarExample::update, TabBarExample::view)
48-
.font(iced_fonts::REQUIRED_FONT_BYTES)
49-
.font(ICON_BYTES)
50-
.run()
48+
iced::application(
49+
TabBarExample::default,
50+
TabBarExample::update,
51+
TabBarExample::view,
52+
)
53+
.font(ICED_AW_FONT_BYTES)
54+
.font(ICON_BYTES)
55+
.run()
5156
}
5257

5358
#[derive(Default)]

examples/tabs/settings.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,6 @@ pub struct TabSettings {
3333
pub tab_bar_theme_id: Option<usize>,
3434
}
3535

36-
impl TabSettings {
37-
pub fn new() -> Self {
38-
TabSettings {
39-
tab_bar_position: Some(TabBarPosition::Top),
40-
tab_bar_theme: Some(0),
41-
tab_bar_theme_id: Some(0),
42-
}
43-
}
44-
}
45-
4636
#[derive(Debug, Clone)]
4737
pub enum SettingsMessage {
4838
PositionSelected(TabBarPosition),
@@ -55,12 +45,6 @@ pub struct SettingsTab {
5545
}
5646

5747
impl SettingsTab {
58-
pub fn new() -> Self {
59-
SettingsTab {
60-
settings: TabSettings::new(),
61-
}
62-
}
63-
6448
pub fn settings(&self) -> &TabSettings {
6549
&self.settings
6650
}

src/widget/tab_bar.rs

Lines changed: 74 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,20 @@ use iced::{
1414
widget::Tree,
1515
Clipboard, Layout, Shell, Widget,
1616
},
17-
alignment::{self, Horizontal, Vertical},
18-
event,
17+
alignment::{self, Vertical},
1918
mouse::{self, Cursor},
2019
touch,
2120
widget::{
2221
text::{self, LineHeight, Wrapping},
2322
Column, Row, Text,
2423
},
25-
Alignment, Background, Border, Color, Element, Event, Font, Length, Padding, Pixels, Point,
24+
window, Alignment, Background, Border, Color, Element, Event, Font, Length, Padding, Pixels, Point,
2625
Rectangle, Shadow, Size,
2726
};
28-
use iced_fonts::{
29-
required::{icon_to_string, RequiredIcons},
30-
REQUIRED_FONT,
31-
};
3227

3328
use std::marker::PhantomData;
3429

30+
use crate::iced_aw_font::advanced_text::cancel;
3531
pub use crate::style::{
3632
tab_bar::{self, Catalog, Style},
3733
Status, StyleFn,
@@ -88,6 +84,8 @@ where
8884
tab_labels: Vec<TabLabel>,
8985
/// The vector containing the indices of the tabs.
9086
tab_indices: Vec<TabId>,
87+
/// The statuses of the [`TabLabel`] and cross
88+
tab_statuses: Vec<(Option<Status>, Option<bool>)>,
9189
/// The function that produces the message when a tab is selected.
9290
on_select: Box<dyn Fn(TabId) -> Message>,
9391
/// The function that produces the message when the close icon was pressed.
@@ -170,6 +168,7 @@ where
170168
Self {
171169
active_tab: 0,
172170
tab_indices: tab_labels.iter().map(|(id, _)| id.clone()).collect(),
171+
tab_statuses: tab_labels.iter().map(|_| (None, None)).collect(),
173172
tab_labels: tab_labels.into_iter().map(|(_, label)| label).collect(),
174173
on_select: Box::new(on_select),
175174
on_close: None,
@@ -276,6 +275,7 @@ where
276275
pub fn push(mut self, id: TabId, tab_label: TabLabel) -> Self {
277276
self.tab_labels.push(tab_label);
278277
self.tab_indices.push(id);
278+
self.tab_statuses.push((None, None));
279279
self
280280
}
281281

@@ -527,17 +527,17 @@ where
527527
.layout(tab_tree, renderer, &limits.loose())
528528
}
529529

530-
fn on_event(
530+
fn update(
531531
&mut self,
532532
_state: &mut Tree,
533-
event: Event,
533+
event: &Event,
534534
layout: Layout<'_>,
535535
cursor: Cursor,
536536
_renderer: &Renderer,
537537
_clipboard: &mut dyn Clipboard,
538538
shell: &mut Shell<'_, Message>,
539539
_viewport: &Rectangle,
540-
) -> event::Status {
540+
) {
541541
match event {
542542
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
543543
| Event::Touch(touch::Event::FingerPressed { .. }) => {
@@ -569,12 +569,44 @@ where
569569
|on_close| (on_close)(self.tab_indices[new_selected].clone()),
570570
),
571571
);
572-
return event::Status::Captured;
572+
shell.capture_event();
573573
}
574574
}
575-
event::Status::Ignored
576575
}
577-
_ => event::Status::Ignored,
576+
_ => {}
577+
}
578+
579+
let mut request_redraw = false;
580+
let children = layout.children();
581+
for ((i, _tab), layout) in self.tab_labels.iter().enumerate().zip(children) {
582+
let active_idx = self.get_active_tab_idx();
583+
let tab_status = self.tab_statuses.get_mut(i).expect("Should have a status.");
584+
585+
let current_status = if cursor.is_over(layout.bounds()) {
586+
Status::Hovered
587+
} else if i == active_idx {
588+
Status::Active
589+
} else {
590+
Status::Disabled
591+
};
592+
593+
let mut is_cross_hovered = None;
594+
let mut children = layout.children();
595+
if let Some(cross_layout) = children.next_back() {
596+
is_cross_hovered = Some(cursor.is_over(cross_layout.bounds()));
597+
}
598+
599+
if let Event::Window(window::Event::RedrawRequested(_now)) = event {
600+
*tab_status = (Some(current_status), is_cross_hovered);
601+
} else if tab_status.0.is_some_and(|status| status != current_status)
602+
|| tab_status.1 != is_cross_hovered
603+
{
604+
request_redraw = true;
605+
}
606+
}
607+
608+
if request_redraw {
609+
shell.request_redraw();
578610
}
579611
}
580612

@@ -636,24 +668,29 @@ where
636668
color: style_sheet.border_color.unwrap_or(Color::TRANSPARENT),
637669
},
638670
shadow: Shadow::default(),
671+
..renderer::Quad::default()
639672
},
640673
style_sheet
641674
.background
642675
.unwrap_or_else(|| Color::TRANSPARENT.into()),
643676
);
644677
}
645678

679+
let (_content, font, _shaping) = cancel();
680+
646681
for ((i, tab), layout) in self.tab_labels.iter().enumerate().zip(children) {
682+
let tab_status = self.tab_statuses.get(i).expect("Should have a status.");
683+
647684
draw_tab(
648685
renderer,
649686
tab,
687+
tab_status,
650688
layout,
651689
self.position,
652690
theme,
653691
&self.class,
654-
i == self.get_active_tab_idx(),
655692
cursor,
656-
(self.font.unwrap_or(REQUIRED_FONT), self.icon_size),
693+
(self.font.unwrap_or(font), self.icon_size),
657694
(self.text_font.unwrap_or_default(), self.text_size),
658695
self.close_size,
659696
viewport,
@@ -671,12 +708,12 @@ where
671708
fn draw_tab<Theme, Renderer>(
672709
renderer: &mut Renderer,
673710
tab: &TabLabel,
711+
tab_status: &(Option<Status>, Option<bool>),
674712
layout: Layout<'_>,
675713
position: Position,
676714
theme: &Theme,
677715
class: &<Theme as Catalog>::Class<'_>,
678-
is_selected: bool,
679-
cursor: Cursor,
716+
_cursor: Cursor,
680717
icon_data: (Font, f32),
681718
text_data: (Font, f32),
682719
close_size: f32,
@@ -696,15 +733,8 @@ fn draw_tab<Theme, Renderer>(
696733
}
697734

698735
let bounds = layout.bounds();
699-
let is_mouse_over = cursor.position().is_some_and(|pos| bounds.contains(pos));
700-
701-
let style = if is_mouse_over {
702-
tab_bar::Catalog::style(theme, class, Status::Hovered)
703-
} else if is_selected {
704-
tab_bar::Catalog::style(theme, class, Status::Active)
705-
} else {
706-
tab_bar::Catalog::style(theme, class, Status::Disabled)
707-
};
736+
737+
let style = tab_bar::Catalog::style(theme, class, tab_status.0.unwrap_or(Status::Disabled));
708738

709739
let mut children = layout.children();
710740
let label_layout = children
@@ -722,6 +752,7 @@ fn draw_tab<Theme, Renderer>(
722752
color: style.tab_label_border_color,
723753
},
724754
shadow: Shadow::default(),
755+
..renderer::Quad::default()
725756
},
726757
style.tab_label_background,
727758
);
@@ -737,8 +768,8 @@ fn draw_tab<Theme, Renderer>(
737768
bounds: Size::new(icon_bounds.width, icon_bounds.height),
738769
size: Pixels(icon_data.1),
739770
font: icon_data.0,
740-
horizontal_alignment: Horizontal::Center,
741-
vertical_alignment: Vertical::Center,
771+
align_x: text::Alignment::Center,
772+
align_y: Vertical::Center,
742773
line_height: LineHeight::Relative(1.3),
743774
shaping: iced::advanced::text::Shaping::Advanced,
744775
wrapping: Wrapping::default(),
@@ -758,8 +789,8 @@ fn draw_tab<Theme, Renderer>(
758789
bounds: Size::new(text_bounds.width, text_bounds.height),
759790
size: Pixels(text_data.1),
760791
font: text_data.0,
761-
horizontal_alignment: Horizontal::Center,
762-
vertical_alignment: Vertical::Center,
792+
align_x: text::Alignment::Center,
793+
align_y: Vertical::Center,
763794
line_height: LineHeight::Relative(1.3),
764795
shaping: iced::advanced::text::Shaping::Advanced,
765796
wrapping: Wrapping::default(),
@@ -806,8 +837,8 @@ fn draw_tab<Theme, Renderer>(
806837
bounds: Size::new(icon_bounds.width, icon_bounds.height),
807838
size: Pixels(icon_data.1),
808839
font: icon_data.0,
809-
horizontal_alignment: Horizontal::Center,
810-
vertical_alignment: Vertical::Center,
840+
align_x: text::Alignment::Center,
841+
align_y: Vertical::Center,
811842
line_height: LineHeight::Relative(1.3),
812843
shaping: iced::advanced::text::Shaping::Advanced,
813844
wrapping: Wrapping::default(),
@@ -823,8 +854,8 @@ fn draw_tab<Theme, Renderer>(
823854
bounds: Size::new(text_bounds.width, text_bounds.height),
824855
size: Pixels(text_data.1),
825856
font: text_data.0,
826-
horizontal_alignment: Horizontal::Center,
827-
vertical_alignment: Vertical::Center,
857+
align_x: text::Alignment::Center,
858+
align_y: Vertical::Center,
828859
line_height: LineHeight::Relative(1.3),
829860
shaping: iced::advanced::text::Shaping::Advanced,
830861
wrapping: Wrapping::default(),
@@ -838,18 +869,20 @@ fn draw_tab<Theme, Renderer>(
838869

839870
if let Some(cross_layout) = children.next() {
840871
let cross_bounds = cross_layout.bounds();
841-
let is_mouse_over_cross = cursor.is_over(cross_bounds);
872+
let is_mouse_over_cross = tab_status.1.unwrap_or(false);
873+
874+
let (content, font, shaping) = cancel();
842875

843876
renderer.fill_text(
844877
iced::advanced::text::Text {
845-
content: icon_to_string(RequiredIcons::X),
878+
content,
846879
bounds: Size::new(cross_bounds.width, cross_bounds.height),
847880
size: Pixels(close_size + if is_mouse_over_cross { 1.0 } else { 0.0 }),
848-
font: REQUIRED_FONT,
849-
horizontal_alignment: Horizontal::Center,
850-
vertical_alignment: Vertical::Center,
881+
font,
882+
align_x: text::Alignment::Center,
883+
align_y: Vertical::Center,
851884
line_height: LineHeight::Relative(1.3),
852-
shaping: iced::advanced::text::Shaping::Advanced,
885+
shaping,
853886
wrapping: Wrapping::default(),
854887
},
855888
Point::new(cross_bounds.center_x(), cross_bounds.center_y()),
@@ -867,6 +900,7 @@ fn draw_tab<Theme, Renderer>(
867900
color: style.border_color.unwrap_or(Color::TRANSPARENT),
868901
},
869902
shadow: Shadow::default(),
903+
..renderer::Quad::default()
870904
},
871905
style
872906
.icon_background

0 commit comments

Comments
 (0)