Detailed changes
@@ -170,7 +170,7 @@ dependencies = [
"context_server",
"ctor",
"db",
- "derive_more 0.99.20",
+ "derive_more",
"editor",
"env_logger 0.11.8",
"eval_utils",
@@ -242,7 +242,7 @@ dependencies = [
"anyhow",
"async-broadcast",
"async-trait",
- "derive_more 2.0.1",
+ "derive_more",
"futures 0.3.31",
"log",
"serde",
@@ -256,7 +256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44bc1fef9c32f03bce2ab44af35b6f483bfd169bf55cc59beeb2e3b1a00ae4d1"
dependencies = [
"anyhow",
- "derive_more 2.0.1",
+ "derive_more",
"schemars",
"serde",
"serde_json",
@@ -815,7 +815,7 @@ dependencies = [
"anyhow",
"async-trait",
"collections",
- "derive_more 0.99.20",
+ "derive_more",
"extension",
"futures 0.3.31",
"gpui",
@@ -3002,7 +3002,7 @@ dependencies = [
"cloud_llm_client",
"collections",
"credentials_provider",
- "derive_more 0.99.20",
+ "derive_more",
"feature_flags",
"fs",
"futures 0.3.31",
@@ -3440,7 +3440,7 @@ name = "command_palette_hooks"
version = "0.1.0"
dependencies = [
"collections",
- "derive_more 0.99.20",
+ "derive_more",
"gpui",
"workspace",
]
@@ -3616,15 +3616,18 @@ dependencies = [
[[package]]
name = "convert_case"
-version = "0.4.0"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
+checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f"
+dependencies = [
+ "unicode-segmentation",
+]
[[package]]
name = "convert_case"
-version = "0.8.0"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f"
+checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9"
dependencies = [
"unicode-segmentation",
]
@@ -4794,34 +4797,23 @@ dependencies = [
[[package]]
name = "derive_more"
-version = "0.99.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f"
-dependencies = [
- "convert_case 0.4.0",
- "proc-macro2",
- "quote",
- "rustc_version",
- "syn 2.0.106",
-]
-
-[[package]]
-name = "derive_more"
-version = "2.0.1"
+version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678"
+checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134"
dependencies = [
"derive_more-impl",
]
[[package]]
name = "derive_more-impl"
-version = "2.0.1"
+version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
+checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb"
dependencies = [
+ "convert_case 0.10.0",
"proc-macro2",
"quote",
+ "rustc_version",
"syn 2.0.106",
"unicode-xid",
]
@@ -7130,7 +7122,7 @@ version = "0.8.0"
source = "git+https://github.com/zed-industries/gh-workflow?rev=c9eac0ed361583e1072860d96776fa52775b82ac#c9eac0ed361583e1072860d96776fa52775b82ac"
dependencies = [
"async-trait",
- "derive_more 2.0.1",
+ "derive_more",
"derive_setters",
"gh-workflow-macros",
"indexmap",
@@ -7199,7 +7191,7 @@ dependencies = [
"askpass",
"async-trait",
"collections",
- "derive_more 0.99.20",
+ "derive_more",
"futures 0.3.31",
"git2",
"gpui",
@@ -7578,7 +7570,7 @@ dependencies = [
"core-text",
"core-video",
"ctor",
- "derive_more 0.99.20",
+ "derive_more",
"embed-resource",
"env_logger 0.11.8",
"etagere",
@@ -7706,7 +7698,7 @@ dependencies = [
"core-text",
"core-video",
"ctor",
- "derive_more 0.99.20",
+ "derive_more",
"dispatch2",
"etagere",
"foreign-types 0.5.0",
@@ -8264,7 +8256,7 @@ dependencies = [
"async-fs",
"async-tar",
"bytes 1.11.1",
- "derive_more 0.99.20",
+ "derive_more",
"futures 0.3.31",
"http 1.3.1",
"http-body 1.0.1",
@@ -15556,7 +15548,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"collections",
- "derive_more 0.99.20",
+ "derive_more",
"gpui",
"log",
"schemars",
@@ -17339,7 +17331,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"collections",
- "derive_more 0.99.20",
+ "derive_more",
"fs",
"futures 0.3.31",
"gpui",
@@ -538,7 +538,16 @@ criterion = { version = "0.5", features = ["html_reports"] }
ctor = "0.4.0"
dap-types = { git = "https://github.com/zed-industries/dap-types", rev = "1b461b310481d01e02b2603c16d7144b926339f8" }
dashmap = "6.0"
-derive_more = "0.99.17"
+derive_more = { version = "2.1.1", features = [
+ "add",
+ "add_assign",
+ "deref",
+ "deref_mut",
+ "from_str",
+ "mul",
+ "mul_assign",
+ "not",
+] }
dirs = "4.0"
documented = "0.9.1"
dotenvy = "0.15.0"
@@ -133,7 +133,7 @@ impl ViewState {
fn set_offset(&mut self, point: Point<Pixels>) {
if point.y >= -Pixels::ZERO {
self.schedule_scroll_up();
- } else if point.y <= -self.scroll_handle.max_offset().height {
+ } else if point.y <= -self.scroll_handle.max_offset().y {
self.schedule_scroll_down();
}
self.scroll_handle.set_offset(point);
@@ -141,7 +141,7 @@ impl ViewState {
}
impl ScrollableHandle for ViewStateHandle {
- fn max_offset(&self) -> gpui::Size<Pixels> {
+ fn max_offset(&self) -> gpui::Point<Pixels> {
self.0.borrow().scroll_handle.max_offset()
}
@@ -1886,18 +1886,18 @@ impl Interactivity {
// high for the maximum scroll, we round the scroll max to 2 decimal
// places here.
let padded_content_size = self.content_size + padding_size;
- let scroll_max = (padded_content_size - bounds.size)
+ let scroll_max = Point::from(padded_content_size - bounds.size)
.map(round_to_two_decimals)
.max(&Default::default());
// Clamp scroll offset in case scroll max is smaller now (e.g., if children
// were removed or the bounds became larger).
let mut scroll_offset = scroll_offset.borrow_mut();
- scroll_offset.x = scroll_offset.x.clamp(-scroll_max.width, px(0.));
+ scroll_offset.x = scroll_offset.x.clamp(-scroll_max.x, px(0.));
if scroll_to_bottom {
- scroll_offset.y = -scroll_max.height;
+ scroll_offset.y = -scroll_max.y;
} else {
- scroll_offset.y = scroll_offset.y.clamp(-scroll_max.height, px(0.));
+ scroll_offset.y = scroll_offset.y.clamp(-scroll_max.y, px(0.));
}
if let Some(mut scroll_handle_state) = tracked_scroll_handle {
@@ -3285,7 +3285,7 @@ impl ScrollAnchor {
struct ScrollHandleState {
offset: Rc<RefCell<Point<Pixels>>>,
bounds: Bounds<Pixels>,
- max_offset: Size<Pixels>,
+ max_offset: Point<Pixels>,
child_bounds: Vec<Bounds<Pixels>>,
scroll_to_bottom: bool,
overflow: Point<Overflow>,
@@ -3329,7 +3329,7 @@ impl ScrollHandle {
}
/// Get the maximum scroll offset.
- pub fn max_offset(&self) -> Size<Pixels> {
+ pub fn max_offset(&self) -> Point<Pixels> {
self.0.borrow().max_offset
}
@@ -491,7 +491,7 @@ impl ListState {
/// Returns the maximum scroll offset according to the items we have measured.
/// This value remains constant while dragging to prevent the scrollbar from moving away unexpectedly.
- pub fn max_offset_for_scrollbar(&self) -> Size<Pixels> {
+ pub fn max_offset_for_scrollbar(&self) -> Point<Pixels> {
let state = self.0.borrow();
let bounds = state.last_layout_bounds.unwrap_or_default();
@@ -499,7 +499,7 @@ impl ListState {
.scrollbar_drag_start_height
.unwrap_or_else(|| state.items.summary().height);
- Size::new(Pixels::ZERO, Pixels::ZERO.max(height - bounds.size.height))
+ point(Pixels::ZERO, Pixels::ZERO.max(height - bounds.size.height))
}
/// Returns the current scroll offset adjusted for the scrollbar
@@ -3,8 +3,7 @@ use std::{fs, path::Path, sync::Arc};
use crate::{
App, Asset, Bounds, Element, GlobalElementId, Hitbox, InspectorElementId, InteractiveElement,
Interactivity, IntoElement, LayoutId, Pixels, Point, Radians, SharedString, Size,
- StyleRefinement, Styled, TransformationMatrix, Window, geometry::Negate as _, point, px,
- radians, size,
+ StyleRefinement, Styled, TransformationMatrix, Window, point, px, radians, size,
};
use gpui_util::ResultExt;
@@ -254,7 +253,7 @@ impl Transformation {
.translate(center.scale(scale_factor) + self.translate.scale(scale_factor))
.rotate(self.rotate)
.scale(self.scale)
- .translate(center.scale(scale_factor).negate())
+ .translate(center.scale(-scale_factor))
}
}
@@ -78,6 +78,7 @@ pub trait Along {
Deserialize,
JsonSchema,
Hash,
+ Neg,
)]
#[refineable(Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[repr(C)]
@@ -182,12 +183,6 @@ impl<T: Clone + Debug + Default + PartialEq> Along for Point<T> {
}
}
-impl<T: Clone + Debug + Default + PartialEq + Negate> Negate for Point<T> {
- fn negate(self) -> Self {
- self.map(Negate::negate)
- }
-}
-
impl Point<Pixels> {
/// Scales the point by a given factor, which is typically derived from the resolution
/// of a target display to ensure proper sizing of UI elements.
@@ -393,7 +388,9 @@ impl<T: Clone + Debug + Default + PartialEq + Display> Display for Point<T> {
///
/// This struct is generic over the type `T`, which can be any type that implements `Clone`, `Default`, and `Debug`.
/// It is commonly used to specify dimensions for elements in a UI, such as a window or element.
-#[derive(Refineable, Default, Clone, Copy, PartialEq, Div, Hash, Serialize, Deserialize)]
+#[derive(
+ Add, Clone, Copy, Default, Deserialize, Div, Hash, Neg, PartialEq, Refineable, Serialize, Sub,
+)]
#[refineable(Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[repr(C)]
pub struct Size<T: Clone + Debug + Default + PartialEq> {
@@ -598,34 +595,6 @@ where
}
}
-impl<T> Sub for Size<T>
-where
- T: Sub<Output = T> + Clone + Debug + Default + PartialEq,
-{
- type Output = Size<T>;
-
- fn sub(self, rhs: Self) -> Self::Output {
- Size {
- width: self.width - rhs.width,
- height: self.height - rhs.height,
- }
- }
-}
-
-impl<T> Add for Size<T>
-where
- T: Add<Output = T> + Clone + Debug + Default + PartialEq,
-{
- type Output = Size<T>;
-
- fn add(self, rhs: Self) -> Self::Output {
- Size {
- width: self.width + rhs.width,
- height: self.height + rhs.height,
- }
- }
-}
-
impl<T, Rhs> Mul<Rhs> for Size<T>
where
T: Mul<Rhs, Output = Rhs> + Clone + Debug + Default + PartialEq,
@@ -1245,6 +1214,15 @@ where
}
}
+impl<T: Clone + Debug + Default + PartialEq> From<Size<T>> for Point<T> {
+ fn from(size: Size<T>) -> Self {
+ Self {
+ x: size.width,
+ y: size.height,
+ }
+ }
+}
+
impl<T> Bounds<T>
where
T: Add<T, Output = T> + Clone + Debug + Default + PartialEq,
@@ -3754,48 +3732,6 @@ impl Half for Rems {
}
}
-/// Provides a trait for types that can negate their values.
-pub trait Negate {
- /// Returns the negation of the given value
- fn negate(self) -> Self;
-}
-
-impl Negate for i32 {
- fn negate(self) -> Self {
- -self
- }
-}
-
-impl Negate for f32 {
- fn negate(self) -> Self {
- -self
- }
-}
-
-impl Negate for DevicePixels {
- fn negate(self) -> Self {
- Self(-self.0)
- }
-}
-
-impl Negate for ScaledPixels {
- fn negate(self) -> Self {
- Self(-self.0)
- }
-}
-
-impl Negate for Pixels {
- fn negate(self) -> Self {
- Self(-self.0)
- }
-}
-
-impl Negate for Rems {
- fn negate(self) -> Self {
- Self(-self.0)
- }
-}
-
/// A trait for checking if a value is zero.
///
/// This trait provides a method to determine if a value is considered to be zero.
@@ -464,7 +464,7 @@ impl Render for ProfilerWindow {
let scroll_offset = self.scroll_handle.offset();
let max_offset = self.scroll_handle.max_offset();
- self.autoscroll = -scroll_offset.y >= (max_offset.height - px(24.));
+ self.autoscroll = -scroll_offset.y >= (max_offset.y - px(24.));
if self.autoscroll {
self.scroll_handle.scroll_to_bottom();
}
@@ -46,6 +46,7 @@ use settings::{
update_settings_file,
};
use smallvec::SmallVec;
+use std::ops::Neg;
use std::{any::TypeId, time::Instant};
use std::{
cell::OnceCell,
@@ -6691,6 +6692,24 @@ impl Render for ProjectPanel {
.id("project-panel-blank-area")
.block_mouse_except_scroll()
.flex_grow()
+ .on_scroll_wheel({
+ let scroll_handle = self.scroll_handle.clone();
+ let entity_id = cx.entity().entity_id();
+ move |event, window, cx| {
+ let state = scroll_handle.0.borrow();
+ let base_handle = &state.base_handle;
+ let current_offset = base_handle.offset();
+ let max_offset = base_handle.max_offset();
+ let delta = event.delta.pixel_delta(window.line_height());
+ let new_offset = (current_offset + delta)
+ .clamp(&max_offset.neg(), &Point::default());
+
+ if new_offset != current_offset {
+ base_handle.set_offset(new_offset);
+ cx.notify(entity_id);
+ }
+ }
+ })
.when(
self.drag_target_entry.as_ref().is_some_and(
|entry| match entry {
@@ -3,7 +3,7 @@ use std::{
rc::Rc,
};
-use gpui::{Bounds, Point, Size, size};
+use gpui::{Bounds, Point, point, size};
use terminal::Terminal;
use ui::{Pixels, ScrollableHandle, px};
@@ -46,9 +46,9 @@ impl TerminalScrollHandle {
}
impl ScrollableHandle for TerminalScrollHandle {
- fn max_offset(&self) -> Size<Pixels> {
+ fn max_offset(&self) -> Point<Pixels> {
let state = self.state.borrow();
- size(
+ point(
Pixels::ZERO,
state.total_lines.saturating_sub(state.viewport_lines) as f32 * state.line_height,
)
@@ -9,8 +9,8 @@ use gpui::{
Along, App, AppContext as _, Axis as ScrollbarAxis, BorderStyle, Bounds, ContentMask, Context,
Corner, Corners, CursorStyle, DispatchPhase, Div, Edges, Element, ElementId, Entity, EntityId,
GlobalElementId, Hitbox, HitboxBehavior, Hsla, InteractiveElement, IntoElement, IsZero,
- LayoutId, ListState, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Negate,
- ParentElement, Pixels, Point, Position, Render, ScrollHandle, ScrollWheelEvent, Size, Stateful,
+ LayoutId, ListState, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement,
+ Pixels, Point, Position, Render, ScrollHandle, ScrollWheelEvent, Size, Stateful,
StatefulInteractiveElement, Style, Styled, Task, UniformListDecoration,
UniformListScrollHandle, Window, ease_in_out, prelude::FluentBuilder as _, px, quad, relative,
size,
@@ -258,7 +258,7 @@ impl<T: ScrollableHandle> UniformListDecoration for ScrollbarStateWrapper<T> {
_cx: &mut App,
) -> gpui::AnyElement {
ScrollbarElement {
- origin: scroll_offset.negate(),
+ origin: -scroll_offset,
state: self.0.clone(),
}
.into_any()
@@ -911,7 +911,7 @@ impl ThumbState {
}
impl ScrollableHandle for UniformListScrollHandle {
- fn max_offset(&self) -> Size<Pixels> {
+ fn max_offset(&self) -> Point<Pixels> {
self.0.borrow().base_handle.max_offset()
}
@@ -929,7 +929,7 @@ impl ScrollableHandle for UniformListScrollHandle {
}
impl ScrollableHandle for ListState {
- fn max_offset(&self) -> Size<Pixels> {
+ fn max_offset(&self) -> Point<Pixels> {
self.max_offset_for_scrollbar()
}
@@ -955,7 +955,7 @@ impl ScrollableHandle for ListState {
}
impl ScrollableHandle for ScrollHandle {
- fn max_offset(&self) -> Size<Pixels> {
+ fn max_offset(&self) -> Point<Pixels> {
self.max_offset()
}
@@ -973,7 +973,7 @@ impl ScrollableHandle for ScrollHandle {
}
pub trait ScrollableHandle: 'static + Any + Sized + Clone {
- fn max_offset(&self) -> Size<Pixels>;
+ fn max_offset(&self) -> Point<Pixels>;
fn set_offset(&self, point: Point<Pixels>);
fn offset(&self) -> Point<Pixels>;
fn viewport(&self) -> Bounds<Pixels>;
@@ -984,7 +984,7 @@ pub trait ScrollableHandle: 'static + Any + Sized + Clone {
self.max_offset().along(axis) > Pixels::ZERO
}
fn content_size(&self) -> Size<Pixels> {
- self.viewport().size + self.max_offset()
+ self.viewport().size + self.max_offset().into()
}
}
@@ -1006,7 +1006,7 @@ impl ScrollbarLayout {
fn compute_click_offset(
&self,
event_position: Point<Pixels>,
- max_offset: Size<Pixels>,
+ max_offset: Point<Pixels>,
event_type: ScrollbarMouseEvent,
) -> Pixels {
let Self {
@@ -3450,7 +3450,7 @@ impl Pane {
cx,
)
.children(pinned_tabs.len().ne(&0).then(|| {
- let max_scroll = self.tab_bar_scroll_handle.max_offset().width;
+ let max_scroll = self.tab_bar_scroll_handle.max_offset().x;
// We need to check both because offset returns delta values even when the scroll handle is not scrollable
let is_scrolled = self.tab_bar_scroll_handle.offset().x < px(0.);
// Avoid flickering when max_offset is very small (< 2px).
@@ -7974,7 +7974,7 @@ mod tests {
let scroll_handle =
pane.update_in(cx, |pane, _window, _cx| pane.tab_bar_scroll_handle.clone());
assert!(
- scroll_handle.max_offset().width > px(0.),
+ scroll_handle.max_offset().x > px(0.),
"Test requires tab overflow to verify scrolling. Increase tab count or reduce window width."
);