Improve local tool execution and shell output panes
This commit is contained in:
@@ -38,6 +38,8 @@ pub struct ScrollTarget {
|
||||
#[derive(Clone, Default)]
|
||||
pub struct ClippedScrollData {
|
||||
scroll_start_px: Pixels,
|
||||
max_scroll_start_px: Pixels,
|
||||
follow_end: bool,
|
||||
pub(super) scroll_to_position: Option<ScrollTarget>,
|
||||
selection_scroll_anchor: Option<ClippedSelectionScrollAnchor>,
|
||||
}
|
||||
@@ -77,6 +79,36 @@ impl ClippedScrollStateHandle {
|
||||
self.clipped_scroll_data.lock().scroll_start_px
|
||||
}
|
||||
|
||||
/// Returns whether the scrollable is currently at its maximum scroll position.
|
||||
///
|
||||
/// The maximum is captured during layout, so consumers can implement follow-output
|
||||
/// behavior without estimating content or viewport sizes themselves.
|
||||
pub fn is_scrolled_to_end(&self) -> bool {
|
||||
let data = self.clipped_scroll_data.lock();
|
||||
data.scroll_start_px.as_f32() + 0.5 >= data.max_scroll_start_px.as_f32()
|
||||
}
|
||||
|
||||
/// Controls whether layout should keep the scroll position docked to the content's end.
|
||||
pub fn set_follow_end(&self, follow_end: bool) {
|
||||
self.clipped_scroll_data.lock().follow_end = follow_end;
|
||||
}
|
||||
|
||||
pub(in crate::elements) fn update_scroll_extent(
|
||||
&self,
|
||||
visible_px: Pixels,
|
||||
total_size: Pixels,
|
||||
) -> Pixels {
|
||||
let max_scroll_start_px = (total_size - visible_px).max(Pixels::zero());
|
||||
let mut data = self.clipped_scroll_data.lock();
|
||||
data.max_scroll_start_px = max_scroll_start_px;
|
||||
data.scroll_start_px = if data.follow_end {
|
||||
max_scroll_start_px
|
||||
} else {
|
||||
data.scroll_start_px.min(max_scroll_start_px)
|
||||
};
|
||||
data.scroll_start_px
|
||||
}
|
||||
|
||||
pub fn scroll_by(&self, delta: Pixels) {
|
||||
self.scroll_to(self.scroll_start() + delta);
|
||||
}
|
||||
@@ -417,12 +449,8 @@ impl Element for ClippedScrollable {
|
||||
// Make sure that the new layout doesn't put the scroll bar in an invalid
|
||||
// location.
|
||||
if let Some(scroll_data) = self.scroll_data(app) {
|
||||
let max_scroll_top =
|
||||
(scroll_data.total_size - scroll_data.visible_px).max(Pixels::zero());
|
||||
let scroll_top = scroll_data.scroll_start;
|
||||
if scroll_top > max_scroll_top {
|
||||
self.state.scroll_to(max_scroll_top);
|
||||
}
|
||||
self.state
|
||||
.update_scroll_extent(scroll_data.visible_px, scroll_data.total_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1577,10 +1577,12 @@ impl SelectableElement for NewScrollable {
|
||||
|
||||
impl ClippedScrollStateHandle {
|
||||
fn scroll_data(&self, viewport_size: Vector2F, child_size: Vector2F, axis: Axis) -> ScrollData {
|
||||
let visible_px = viewport_size.along(axis).into_pixels();
|
||||
let total_size = child_size.along(axis).into_pixels();
|
||||
ScrollData {
|
||||
scroll_start: self.scroll_start(),
|
||||
visible_px: (viewport_size.along(axis)).into_pixels(),
|
||||
total_size: child_size.along(axis).into_pixels(),
|
||||
scroll_start: self.update_scroll_extent(visible_px, total_size),
|
||||
visible_px,
|
||||
total_size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user