Skip to content

Commit 965237d

Browse files
committed
improv(stack): store scrolling state when updating Tabs layout
1 parent 38fe84a commit 965237d

File tree

1 file changed

+22
-21
lines changed

1 file changed

+22
-21
lines changed

src/shell/element/stack/tabs.rs

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ struct TabAnimationState {
5858
#[derive(Debug, Clone)]
5959
pub struct State {
6060
offset_x: Offset,
61+
scrolling: bool,
6162
scroll_animation: Option<ScrollAnimationState>,
6263
scroll_to: Option<usize>,
6364
last_state: Option<HashMap<Id, Rectangle>>,
@@ -99,6 +100,7 @@ impl Default for State {
99100
fn default() -> Self {
100101
State {
101102
offset_x: Offset::Absolute(0.),
103+
scrolling: false,
102104
scroll_animation: None,
103105
scroll_to: None,
104106
last_state: None,
@@ -342,6 +344,8 @@ where
342344

343345
#[allow(clippy::too_many_lines)]
344346
fn layout(&self, tree: &mut Tree, renderer: &cosmic::Renderer, limits: &Limits) -> Node {
347+
let state = tree.state.downcast_mut::<State>();
348+
345349
let limits = limits.width(self.width).height(self.height);
346350

347351
// calculate the smallest possible size
@@ -367,8 +371,8 @@ where
367371
height: a.height.max(b.height),
368372
});
369373
let size = limits.resolve(self.width, self.height, min_size);
370-
371-
if min_size.width <= size.width {
374+
state.scrolling = min_size.width > size.width;
375+
if !state.scrolling {
372376
// we don't need to scroll
373377

374378
// can we make every tab equal weight and keep the active large enough?
@@ -524,8 +528,7 @@ where
524528
);
525529
draw_background(renderer, &background_style, bounds);
526530

527-
let scrolling = content_bounds.width.floor() > bounds.width;
528-
if scrolling {
531+
if state.scrolling {
529532
bounds.width -= 64.;
530533
bounds.x += 30.;
531534
}
@@ -536,7 +539,7 @@ where
536539
..bounds
537540
};
538541

539-
if scrolling {
542+
if state.scrolling {
540543
// we have scroll buttons
541544
for ((scroll, state), layout) in self
542545
.elements
@@ -562,7 +565,7 @@ where
562565
/ TAB_ANIMATION_DURATION.as_millis() as f32;
563566
ease(EaseOutCubic, 0.0, 1.0, percentage)
564567
} else {
565-
1.0
568+
1.0f32
566569
};
567570

568571
for ((tab, wstate), layout) in self.elements[2..self.elements.len() - 3]
@@ -594,9 +597,9 @@ where
594597
height: layout.bounds().height,
595598
});
596599
Rectangle {
597-
x: previous.x + (next.x - previous.x) * percentage,
598-
y: previous.y + (next.y - previous.y) * percentage,
599-
width: previous.width + (next.width - previous.width) * percentage,
600+
x: percentage.mul_add(next.x - previous.x, previous.x),
601+
y: percentage.mul_add(next.y - previous.y, previous.y),
602+
width: percentage.mul_add(next.width - previous.width, previous.width),
600603
height: next.height,
601604
}
602605
} else {
@@ -640,7 +643,7 @@ where
640643
viewport,
641644
);
642645

643-
if !scrolling && self.group_focused {
646+
if !state.scrolling && self.group_focused {
644647
// HACK, overdraw our rule at the edges
645648
self.elements[0].as_widget().draw(
646649
&tree.children[2].children[0],
@@ -662,7 +665,7 @@ where
662665
);
663666
}
664667

665-
if scrolling {
668+
if state.scrolling {
666669
// we have scroll buttons
667670
for ((scroll, state), layout) in self.elements
668671
[self.elements.len() - 2..self.elements.len()]
@@ -732,7 +735,6 @@ where
732735
width: a.width + b.bounds().width,
733736
height: b.bounds().height,
734737
});
735-
let scrolling = content_bounds.width.floor() > bounds.width;
736738

737739
let current_state = self.elements[2..self.elements.len() - 3]
738740
.iter()
@@ -781,7 +783,7 @@ where
781783
};
782784

783785
if unknown_keys || changes.is_some() {
784-
if !scrolling || !matches!(changes, Some(Difference::Focus)) {
786+
if !state.scrolling || !matches!(changes, Some(Difference::Focus)) {
785787
let start_time = Instant::now();
786788

787789
State::discard_expired_tab_animations(&mut state.tab_animations, start_time);
@@ -798,7 +800,7 @@ where
798800
*last_state = current_state;
799801
}
800802

801-
if scrolling {
803+
if state.scrolling {
802804
bounds.x += 30.;
803805
bounds.width -= 64.;
804806
}
@@ -808,7 +810,7 @@ where
808810
state.scroll_to = Some(idx);
809811
}
810812
if let Some(idx) = state.scroll_to.take() {
811-
if scrolling {
813+
if state.scrolling {
812814
let tab_bounds = layout.children().nth(idx + 2).unwrap().bounds();
813815
let left_offset = tab_bounds.x - layout.bounds().x - 30.;
814816
let right_offset = left_offset + tab_bounds.width + 4.;
@@ -850,7 +852,7 @@ where
850852
let mut internal_shell = Shell::new(&mut messages);
851853

852854
let len = self.elements.len();
853-
let result = if scrolling && cursor.position().is_some_and(|pos| pos.x < bounds.x) {
855+
let result = if state.scrolling && cursor.position().is_some_and(|pos| pos.x < bounds.x) {
854856
self.elements[0..2]
855857
.iter_mut()
856858
.zip(&mut tree.children)
@@ -868,7 +870,7 @@ where
868870
)
869871
})
870872
.fold(event::Status::Ignored, event::Status::merge)
871-
} else if scrolling
873+
} else if state.scrolling
872874
&& cursor
873875
.position()
874876
.is_some_and(|pos| pos.x >= bounds.x + bounds.width)
@@ -945,9 +947,8 @@ where
945947
width: a.width + b.bounds().width,
946948
height: b.bounds().height,
947949
});
948-
let scrolling = content_bounds.width.floor() > bounds.width;
949950

950-
if scrolling {
951+
if state.scrolling {
951952
bounds.width -= 64.;
952953
bounds.x += 30.;
953954
}
@@ -958,7 +959,7 @@ where
958959
..bounds
959960
};
960961

961-
if scrolling && cursor.position().is_some_and(|pos| pos.x < bounds.x) {
962+
if state.scrolling && cursor.position().is_some_and(|pos| pos.x < bounds.x) {
962963
self.elements[0..2]
963964
.iter()
964965
.zip(&tree.children)
@@ -969,7 +970,7 @@ where
969970
.mouse_interaction(state, layout, cursor, viewport, renderer)
970971
})
971972
.max()
972-
} else if scrolling
973+
} else if state.scrolling
973974
&& cursor
974975
.position()
975976
.is_some_and(|pos| pos.x >= bounds.x + bounds.width)

0 commit comments

Comments
 (0)