Checkpoint
This commit is contained in:
parent
3f7dc59512
commit
ea6755b1ca
15 changed files with 233 additions and 78 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -8542,6 +8542,7 @@ dependencies = [
|
|||
"gpui2",
|
||||
"itertools 0.11.0",
|
||||
"log",
|
||||
"picker2",
|
||||
"rust-embed",
|
||||
"serde",
|
||||
"settings2",
|
||||
|
|
|
@ -2834,7 +2834,7 @@ impl PositionMap {
|
|||
let previous_valid = self.snapshot.clip_point(exact_unclipped, Bias::Left);
|
||||
let next_valid = self.snapshot.clip_point(exact_unclipped, Bias::Right);
|
||||
|
||||
let column_overshoot_after_line_end = (x_overshoot_after_line_end / self.em_advance).into();
|
||||
let column_overshoot_after_line_end = (x_overshoot_after_line_end / self.em_advance) as u32;
|
||||
*exact_unclipped.column_mut() += column_overshoot_after_line_end;
|
||||
PointForPosition {
|
||||
previous_valid,
|
||||
|
|
|
@ -13,6 +13,7 @@ use std::{
|
|||
atomic::{AtomicUsize, Ordering::SeqCst},
|
||||
Arc, Weak,
|
||||
},
|
||||
thread::panicking,
|
||||
};
|
||||
|
||||
slotmap::new_key_type! { pub struct EntityId; }
|
||||
|
@ -140,9 +141,8 @@ impl<'a, T: 'static> core::ops::DerefMut for Lease<'a, T> {
|
|||
|
||||
impl<'a, T> Drop for Lease<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
if self.entity.is_some() {
|
||||
// We don't panic here, because other panics can cause us to drop the lease without ending it cleanly.
|
||||
log::error!("Leases must be ended with EntityMap::end_lease")
|
||||
if self.entity.is_some() && !panicking() {
|
||||
panic!("Leases must be ended with EntityMap::end_lease")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,5 +6,6 @@ mod text;
|
|||
|
||||
pub use div::*;
|
||||
pub use img::*;
|
||||
pub use list::*;
|
||||
pub use svg::*;
|
||||
pub use text::*;
|
||||
|
|
|
@ -2,36 +2,44 @@ use std::ops::Range;
|
|||
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::{AnyElement, Component, Element, ElementId, StyleRefinement, ViewContext};
|
||||
use crate::{
|
||||
point, px, AnyElement, AvailableSpace, BorrowWindow, Bounds, Component, Element, ElementId,
|
||||
LayoutId, Pixels, Size, StyleRefinement, Styled, ViewContext,
|
||||
};
|
||||
|
||||
// We want to support uniform and non-uniform height
|
||||
// We need to make the ID mandatory, to replace the 'state' field
|
||||
// Previous implementation measured the first element as early as possible
|
||||
|
||||
fn list<'a, Id, V, Iter, C>(
|
||||
pub fn list<Id, V, C>(
|
||||
id: Id,
|
||||
f: impl 'static + FnOnce(&'a mut V, Range<usize>, &'a mut ViewContext<V>) -> Iter,
|
||||
item_count: usize,
|
||||
f: impl 'static + Fn(&mut V, Range<usize>, &mut ViewContext<V>) -> SmallVec<[C; 64]>,
|
||||
) -> List<V>
|
||||
where
|
||||
Id: Into<ElementId>,
|
||||
V: 'static,
|
||||
Iter: 'a + Iterator<Item = C>,
|
||||
C: Component<V>,
|
||||
{
|
||||
List {
|
||||
id: id.into(),
|
||||
render_items: Box::new(|view, visible_range, cx| {
|
||||
style: Default::default(),
|
||||
item_count,
|
||||
render_items: Box::new(move |view, visible_range, cx| {
|
||||
f(view, visible_range, cx)
|
||||
.map(|element| element.render())
|
||||
.into_iter()
|
||||
.map(|component| component.render())
|
||||
.collect()
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
struct List<V> {
|
||||
pub struct List<V> {
|
||||
id: ElementId,
|
||||
style: StyleRefinement,
|
||||
item_count: usize,
|
||||
render_items: Box<
|
||||
dyn for<'a> FnOnce(
|
||||
dyn for<'a> Fn(
|
||||
&'a mut V,
|
||||
Range<usize>,
|
||||
&'a mut ViewContext<V>,
|
||||
|
@ -39,8 +47,6 @@ struct List<V> {
|
|||
>,
|
||||
}
|
||||
|
||||
impl<V> List<V> {}
|
||||
|
||||
// #[derive(Debug)]
|
||||
// pub enum ScrollTarget {
|
||||
// Show(usize),
|
||||
|
@ -48,24 +54,30 @@ impl<V> List<V> {}
|
|||
// }
|
||||
|
||||
#[derive(Default)]
|
||||
struct ListState {
|
||||
pub struct ListState {
|
||||
scroll_top: f32,
|
||||
style: StyleRefinement,
|
||||
// todo
|
||||
// scroll_to: Option<ScrollTarget>,
|
||||
}
|
||||
|
||||
impl<V: 'static> Styled for List<V> {
|
||||
fn style(&mut self) -> &mut StyleRefinement {
|
||||
&mut self.style
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static> Element<V> for List<V> {
|
||||
type ElementState = ListState;
|
||||
|
||||
fn id(&self) -> Option<crate::ElementId> {
|
||||
Some(self.id)
|
||||
Some(self.id.clone())
|
||||
}
|
||||
|
||||
fn initialize(
|
||||
&mut self,
|
||||
_: &mut V,
|
||||
element_state: Option<Self::ElementState>,
|
||||
_: &mut crate::ViewContext<V>,
|
||||
_: &mut ViewContext<V>,
|
||||
) -> Self::ElementState {
|
||||
let element_state = element_state.unwrap_or_default();
|
||||
element_state
|
||||
|
@ -73,11 +85,11 @@ impl<V: 'static> Element<V> for List<V> {
|
|||
|
||||
fn layout(
|
||||
&mut self,
|
||||
view_state: &mut V,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut crate::ViewContext<V>,
|
||||
) -> crate::LayoutId {
|
||||
todo!()
|
||||
_view_state: &mut V,
|
||||
_element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> LayoutId {
|
||||
cx.request_layout(&self.computed_style(), None)
|
||||
}
|
||||
|
||||
fn paint(
|
||||
|
@ -85,7 +97,62 @@ impl<V: 'static> Element<V> for List<V> {
|
|||
bounds: crate::Bounds<crate::Pixels>,
|
||||
view_state: &mut V,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut crate::ViewContext<V>,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
let style = self.computed_style();
|
||||
style.paint(bounds, cx);
|
||||
|
||||
let border = style.border_widths.to_pixels(cx.rem_size());
|
||||
let padding = style.padding.to_pixels(bounds.size.into(), cx.rem_size());
|
||||
|
||||
let padded_bounds = Bounds::from_corners(
|
||||
bounds.origin + point(border.left + padding.left, border.top + padding.top),
|
||||
bounds.lower_right()
|
||||
- point(border.right + padding.right, border.bottom + padding.bottom),
|
||||
);
|
||||
|
||||
if self.item_count > 0 {
|
||||
let item_height = self.measure_item_height(view_state, padded_bounds, cx);
|
||||
let visible_item_count = (padded_bounds.size.height / item_height) as usize;
|
||||
let visible_range = 0..visible_item_count;
|
||||
|
||||
let mut items = (self.render_items)(view_state, visible_range, cx);
|
||||
|
||||
for (ix, item) in items.iter_mut().enumerate() {
|
||||
item.initialize(view_state, cx);
|
||||
item.layout(view_state, cx);
|
||||
let offset = padded_bounds.origin + point(px(0.), item_height * ix);
|
||||
cx.with_element_offset(Some(offset), |cx| item.paint(view_state, cx))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> List<V> {
|
||||
fn measure_item_height(
|
||||
&self,
|
||||
view_state: &mut V,
|
||||
list_bounds: Bounds<Pixels>,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Pixels {
|
||||
let mut items = (self.render_items)(view_state, 0..1, cx);
|
||||
debug_assert!(items.len() == 1);
|
||||
let mut item_to_measure = items.pop().unwrap();
|
||||
item_to_measure.initialize(view_state, cx);
|
||||
let layout_id = item_to_measure.layout(view_state, cx);
|
||||
cx.compute_layout(
|
||||
layout_id,
|
||||
Size {
|
||||
width: AvailableSpace::Definite(list_bounds.size.width),
|
||||
height: AvailableSpace::MinContent,
|
||||
},
|
||||
);
|
||||
cx.layout_bounds(layout_id).size.height
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static> Component<V> for List<V> {
|
||||
fn render(self) -> AnyElement<V> {
|
||||
AnyElement::new(self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -259,6 +259,24 @@ impl From<Size<Pixels>> for Size<GlobalPixels> {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Size<Pixels>> for Size<DefiniteLength> {
|
||||
fn from(size: Size<Pixels>) -> Self {
|
||||
Size {
|
||||
width: size.width.into(),
|
||||
height: size.height.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Size<Pixels>> for Size<AbsoluteLength> {
|
||||
fn from(size: Size<Pixels>) -> Self {
|
||||
Size {
|
||||
width: size.width.into(),
|
||||
height: size.height.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Size<Length> {
|
||||
pub fn full() -> Self {
|
||||
Self {
|
||||
|
@ -541,6 +559,15 @@ impl Edges<DefiniteLength> {
|
|||
left: px(0.).into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_pixels(&self, parent_size: Size<AbsoluteLength>, rem_size: Pixels) -> Edges<Pixels> {
|
||||
Edges {
|
||||
top: self.top.to_pixels(parent_size.height, rem_size),
|
||||
right: self.right.to_pixels(parent_size.width, rem_size),
|
||||
bottom: self.bottom.to_pixels(parent_size.height, rem_size),
|
||||
left: self.left.to_pixels(parent_size.width, rem_size),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Edges<AbsoluteLength> {
|
||||
|
@ -672,16 +699,16 @@ impl<T> Copy for Corners<T> where T: Copy + Clone + Default + Debug {}
|
|||
pub struct Pixels(pub(crate) f32);
|
||||
|
||||
impl std::ops::Div for Pixels {
|
||||
type Output = Self;
|
||||
type Output = f32;
|
||||
|
||||
fn div(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 / rhs.0)
|
||||
self.0 / rhs.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DivAssign for Pixels {
|
||||
fn div_assign(&mut self, rhs: Self) {
|
||||
self.0 /= rhs.0;
|
||||
*self = Self(self.0 / rhs.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -732,14 +759,6 @@ impl MulAssign<f32> for Pixels {
|
|||
impl Pixels {
|
||||
pub const MAX: Pixels = Pixels(f32::MAX);
|
||||
|
||||
pub fn as_usize(&self) -> usize {
|
||||
self.0 as usize
|
||||
}
|
||||
|
||||
pub fn as_isize(&self) -> isize {
|
||||
self.0 as isize
|
||||
}
|
||||
|
||||
pub fn floor(&self) -> Self {
|
||||
Self(self.0.floor())
|
||||
}
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
use crate::{
|
||||
self as gpui, hsla, point, px, relative, rems, AlignItems, CursorStyle, DefiniteLength,
|
||||
Display, Fill, FlexDirection, Hsla, JustifyContent, Length, Position, Rems, SharedString,
|
||||
StyleRefinement, Visibility,
|
||||
Style, StyleRefinement, Visibility,
|
||||
};
|
||||
use crate::{BoxShadow, TextStyleRefinement};
|
||||
use refineable::Refineable;
|
||||
use smallvec::smallvec;
|
||||
|
||||
pub trait Styled {
|
||||
fn style(&mut self) -> &mut StyleRefinement;
|
||||
|
||||
fn computed_style(&mut self) -> Style {
|
||||
Style::default().refined(self.style().clone())
|
||||
}
|
||||
|
||||
gpui2_macros::style_helpers!();
|
||||
|
||||
/// Sets the size of the element to the full width and height.
|
||||
|
|
|
@ -559,6 +559,12 @@ impl<'a> WindowContext<'a> {
|
|||
.request_measured_layout(style, rem_size, measure)
|
||||
}
|
||||
|
||||
pub fn compute_layout(&mut self, layout_id: LayoutId, available_space: Size<AvailableSpace>) {
|
||||
self.window
|
||||
.layout_engine
|
||||
.compute_layout(layout_id, available_space)
|
||||
}
|
||||
|
||||
/// Obtain the bounds computed for the given LayoutId relative to the window. This method should not
|
||||
/// be invoked until the paint phase begins, and will usually be invoked by GPUI itself automatically
|
||||
/// in order to pass your element its `Bounds` automatically.
|
||||
|
|
|
@ -20,24 +20,28 @@
|
|||
|
||||
use std::ops::Range;
|
||||
|
||||
use gpui::{div, AppContext, Component, Div, Element, ParentElement, Render, ViewContext};
|
||||
use gpui::{
|
||||
div, list, AppContext, Component, Div, Element, ElementId, ParentElement, Render, ViewContext,
|
||||
};
|
||||
|
||||
pub struct Picker<D> {
|
||||
delegate: D,
|
||||
// query_editor: ViewHandle<Editor>,
|
||||
// list_state: UniformListState,
|
||||
// max_size: Vector2F,
|
||||
// theme: Arc<Mutex<Box<dyn Fn(&theme::Theme) -> theme::Picker>>>,
|
||||
// confirmed: bool,
|
||||
// pending_update_matches: Option<Task<Option<()>>>,
|
||||
// confirm_on_update: Option<bool>,
|
||||
// has_focus: bool,
|
||||
}
|
||||
// pub struct Picker<D> {
|
||||
// delegate: D,
|
||||
// query_editor: ViewHandle<Editor>,
|
||||
// list_state: UniformListState,
|
||||
// max_size: Vector2F,
|
||||
// theme: Arc<Mutex<Box<dyn Fn(&theme::Theme) -> theme::Picker>>>,
|
||||
// confirmed: bool,
|
||||
// pending_update_matches: Option<Task<Option<()>>>,
|
||||
// confirm_on_update: Option<bool>,
|
||||
// has_focus: bool,
|
||||
// }
|
||||
|
||||
pub trait PickerDelegate: Sized + 'static {
|
||||
type ListItem: Element<Picker<Self>>;
|
||||
type ListItem: Component<Self>;
|
||||
// fn placeholder_text(&self) -> Arc<str>;
|
||||
// fn match_count(&self) -> usize;
|
||||
|
||||
fn match_count(&self, picker_id: ElementId) -> usize;
|
||||
|
||||
// fn selected_index(&self) -> usize;
|
||||
// fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>);
|
||||
// fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()>;
|
||||
|
@ -51,7 +55,8 @@ pub trait PickerDelegate: Sized + 'static {
|
|||
active: bool,
|
||||
hovered: bool,
|
||||
selected: bool,
|
||||
cx: &mut ViewContext<Picker<Self>>,
|
||||
picker_id: ElementId,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self::ListItem;
|
||||
|
||||
// fn center_selection_after_match_updates(&self) -> bool {
|
||||
|
@ -75,27 +80,33 @@ pub trait PickerDelegate: Sized + 'static {
|
|||
// type Event = PickerEvent;
|
||||
// }
|
||||
|
||||
impl<D: PickerDelegate> Render for Picker<D> {
|
||||
type Element = Div<Self>;
|
||||
#[derive(Component)]
|
||||
pub struct Picker<V: PickerDelegate> {
|
||||
id: ElementId,
|
||||
phantom: std::marker::PhantomData<V>,
|
||||
}
|
||||
|
||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
|
||||
div().child(list(
|
||||
"candidates",
|
||||
|this: &mut Picker<D>, visible_range, cx| {
|
||||
visible_range
|
||||
.into_iter()
|
||||
.map(|ix| this.delegate.render_match(ix, false, false, false, cx))
|
||||
},
|
||||
))
|
||||
impl<V: PickerDelegate> Picker<V> {
|
||||
pub fn new(id: impl Into<ElementId>) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn list<'a, D: PickerDelegate, F, I>(id: &'static str, f: F) -> Div<Picker<D>>
|
||||
where
|
||||
F: FnOnce(&'a mut Picker<D>, Range<usize>, &'a mut ViewContext<Picker<D>>) -> I,
|
||||
I: 'a + Iterator<Item = D::ListItem>,
|
||||
{
|
||||
todo!();
|
||||
impl<V: 'static + PickerDelegate> Picker<V> {
|
||||
pub fn render(self, view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
|
||||
div().id(self.id.clone()).child(list(
|
||||
"candidates",
|
||||
view.match_count(self.id.clone()),
|
||||
move |this: &mut V, visible_range, cx| {
|
||||
visible_range
|
||||
.map(|ix| this.render_match(ix, false, false, false, self.id.clone(), cx))
|
||||
.collect()
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// impl<D: PickerDelegate> View for Picker<D> {
|
||||
|
@ -213,7 +224,7 @@ where
|
|||
// cx.add_action(Self::cancel);
|
||||
// }
|
||||
|
||||
// pub fn new(delegate: D, cx: &mut ViewContext<Self>) -> Self {
|
||||
// pub fn new(delegate: D, cx: &mut ViewContext<Self>) -> Self {
|
||||
// let theme = Arc::new(Mutex::new(
|
||||
// Box::new(|theme: &theme::Theme| theme.picker.clone())
|
||||
// as Box<dyn Fn(&theme::Theme) -> theme::Picker>,
|
||||
|
@ -247,7 +258,8 @@ where
|
|||
// };
|
||||
// this.update_matches(String::new(), cx);
|
||||
// this
|
||||
// }
|
||||
// Self { delegate }
|
||||
// }
|
||||
|
||||
// pub fn with_max_size(mut self, width: f32, height: f32) -> Self {
|
||||
// self.max_size = vec2f(width, height);
|
||||
|
|
|
@ -27,6 +27,7 @@ theme = { path = "../theme" }
|
|||
theme2 = { path = "../theme2" }
|
||||
ui = { package = "ui2", path = "../ui2", features = ["stories"] }
|
||||
util = { path = "../util" }
|
||||
picker = { package = "picker2", path = "../picker2" }
|
||||
|
||||
[dev-dependencies]
|
||||
gpui = { package = "gpui2", path = "../gpui2", features = ["test-support"] }
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
mod colors;
|
||||
mod focus;
|
||||
mod kitchen_sink;
|
||||
mod picker;
|
||||
mod scroll;
|
||||
mod text;
|
||||
mod z_index;
|
||||
|
@ -8,6 +9,7 @@ mod z_index;
|
|||
pub use colors::*;
|
||||
pub use focus::*;
|
||||
pub use kitchen_sink::*;
|
||||
pub use picker::*;
|
||||
pub use scroll::*;
|
||||
pub use text::*;
|
||||
pub use z_index::*;
|
||||
|
|
40
crates/storybook2/src/stories/picker.rs
Normal file
40
crates/storybook2/src/stories/picker.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
use gpui::{div, Div, ParentElement, Render, View, VisualContext, WindowContext};
|
||||
use picker::{Picker, PickerDelegate};
|
||||
|
||||
pub struct PickerStory {
|
||||
// picker: View<Picker<PickerStoryDelegate>>,
|
||||
}
|
||||
|
||||
impl PickerDelegate for PickerStory {
|
||||
type ListItem = Div<Self>;
|
||||
|
||||
fn match_count(&self, picker_id: gpui::ElementId) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
fn render_match(
|
||||
&self,
|
||||
ix: usize,
|
||||
active: bool,
|
||||
hovered: bool,
|
||||
selected: bool,
|
||||
picker_id: gpui::ElementId,
|
||||
cx: &mut gpui::ViewContext<Self>,
|
||||
) -> Self::ListItem {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl PickerStory {
|
||||
pub fn new(cx: &mut WindowContext) -> View<Self> {
|
||||
cx.build_view(|cx| PickerStory {})
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for PickerStory {
|
||||
type Element = Div<Self>;
|
||||
|
||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
|
||||
div().child(Picker::new("picker_story"))
|
||||
}
|
||||
}
|
|
@ -51,6 +51,7 @@ pub enum ComponentStory {
|
|||
TrafficLights,
|
||||
Workspace,
|
||||
ZIndex,
|
||||
Picker,
|
||||
}
|
||||
|
||||
impl ComponentStory {
|
||||
|
@ -94,6 +95,7 @@ impl ComponentStory {
|
|||
Self::TrafficLights => cx.build_view(|_| ui::TrafficLightsStory).into(),
|
||||
Self::Workspace => ui::WorkspaceStory::view(cx).into(),
|
||||
Self::ZIndex => cx.build_view(|_| ZIndexStory).into(),
|
||||
Self::Picker => PickerStory::new(cx).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -186,9 +186,9 @@ pub fn mouse_side(
|
|||
}
|
||||
|
||||
pub fn grid_point(pos: Point<Pixels>, cur_size: TerminalSize, display_offset: usize) -> AlacPoint {
|
||||
let col = GridCol((pos.x / cur_size.cell_width).as_usize());
|
||||
let col = GridCol((cur_size.cell_width / pos.x) as usize);
|
||||
let col = min(col, cur_size.last_column());
|
||||
let line = (pos.y / cur_size.line_height).as_isize() as i32;
|
||||
let line = (cur_size.line_height / pos.y) as i32;
|
||||
let line = min(line, cur_size.bottommost_line().0);
|
||||
AlacPoint::new(GridLine(line - display_offset as i32), col)
|
||||
}
|
||||
|
|
|
@ -1121,8 +1121,7 @@ impl Terminal {
|
|||
None => return,
|
||||
};
|
||||
|
||||
let scroll_lines =
|
||||
(scroll_delta / self.last_content.size.line_height).as_isize() as i32;
|
||||
let scroll_lines = (scroll_delta / self.last_content.size.line_height) as i32;
|
||||
|
||||
self.events
|
||||
.push_back(InternalEvent::Scroll(AlacScroll::Delta(scroll_lines)));
|
||||
|
@ -1280,11 +1279,11 @@ impl Terminal {
|
|||
}
|
||||
/* Calculate the appropriate scroll lines */
|
||||
TouchPhase::Moved => {
|
||||
let old_offset = (self.scroll_px / line_height).as_isize() as i32;
|
||||
let old_offset = (self.scroll_px / line_height) as i32;
|
||||
|
||||
self.scroll_px += e.delta.pixel_delta(line_height).y * scroll_multiplier;
|
||||
|
||||
let new_offset = (self.scroll_px / line_height).as_isize() as i32;
|
||||
let new_offset = (self.scroll_px / line_height) as i32;
|
||||
|
||||
// Whenever we hit the edges, reset our stored scroll to 0
|
||||
// so we can respond to changes in direction quickly
|
||||
|
@ -1396,9 +1395,9 @@ fn all_search_matches<'a, T>(
|
|||
}
|
||||
|
||||
fn content_index_for_mouse(pos: Point<Pixels>, size: &TerminalSize) -> usize {
|
||||
let col = (pos.x / size.cell_width()).round().as_usize();
|
||||
let col = (pos.x / size.cell_width()).round() as usize;
|
||||
let clamped_col = min(col, size.columns() - 1);
|
||||
let row = (pos.y / size.line_height()).round().as_usize();
|
||||
let row = (pos.y / size.line_height()).round() as usize;
|
||||
let clamped_row = min(row, size.screen_lines() - 1);
|
||||
clamped_row * size.columns() + clamped_col
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue