mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-24 02:46:43 +00:00
Add Corner to geometry and make names of corner methods consistent (#22119)
Release Notes: - N/A
This commit is contained in:
parent
3052fc2565
commit
fc5a810408
39 changed files with 325 additions and 254 deletions
|
@ -493,7 +493,7 @@ impl Render for ActivityIndicator {
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.anchor(gpui::AnchorCorner::BottomLeft)
|
.anchor(gpui::Corner::BottomLeft)
|
||||||
.menu(move |cx| {
|
.menu(move |cx| {
|
||||||
let strong_this = this.upgrade()?;
|
let strong_this = this.upgrade()?;
|
||||||
let mut has_work = false;
|
let mut has_work = false;
|
||||||
|
|
|
@ -1556,7 +1556,7 @@ impl Render for PromptEditor {
|
||||||
anchored()
|
anchored()
|
||||||
.position_mode(gpui::AnchoredPositionMode::Local)
|
.position_mode(gpui::AnchoredPositionMode::Local)
|
||||||
.position(point(px(0.), px(24.)))
|
.position(point(px(0.), px(24.)))
|
||||||
.anchor(gpui::AnchorCorner::TopLeft)
|
.anchor(gpui::Corner::TopLeft)
|
||||||
.child(self.render_rate_limit_notice(cx)),
|
.child(self.render_rate_limit_notice(cx)),
|
||||||
)
|
)
|
||||||
})),
|
})),
|
||||||
|
|
|
@ -316,8 +316,8 @@ impl<T: PopoverTrigger> RenderOnce for SlashCommandSelector<T> {
|
||||||
PopoverMenu::new("model-switcher")
|
PopoverMenu::new("model-switcher")
|
||||||
.menu(move |_cx| Some(picker_view.clone()))
|
.menu(move |_cx| Some(picker_view.clone()))
|
||||||
.trigger(self.trigger)
|
.trigger(self.trigger)
|
||||||
.attach(gpui::AnchorCorner::TopLeft)
|
.attach(gpui::Corner::TopLeft)
|
||||||
.anchor(gpui::AnchorCorner::BottomLeft)
|
.anchor(gpui::Corner::BottomLeft)
|
||||||
.offset(gpui::Point {
|
.offset(gpui::Point {
|
||||||
x: px(0.0),
|
x: px(0.0),
|
||||||
y: px(-16.0),
|
y: px(-16.0),
|
||||||
|
|
|
@ -67,8 +67,8 @@ impl Render for ContextStrip {
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.attach(gpui::AnchorCorner::TopLeft)
|
.attach(gpui::Corner::TopLeft)
|
||||||
.anchor(gpui::AnchorCorner::BottomLeft)
|
.anchor(gpui::Corner::BottomLeft)
|
||||||
.offset(gpui::Point {
|
.offset(gpui::Point {
|
||||||
x: px(0.0),
|
x: px(0.0),
|
||||||
y: px(-16.0),
|
y: px(-16.0),
|
||||||
|
|
|
@ -1673,7 +1673,7 @@ impl Render for PromptEditor {
|
||||||
gpui::AnchoredPositionMode::Local,
|
gpui::AnchoredPositionMode::Local,
|
||||||
)
|
)
|
||||||
.position(point(px(0.), px(24.)))
|
.position(point(px(0.), px(24.)))
|
||||||
.anchor(gpui::AnchorCorner::TopLeft)
|
.anchor(gpui::Corner::TopLeft)
|
||||||
.child(self.render_rate_limit_notice(cx)),
|
.child(self.render_rate_limit_notice(cx)),
|
||||||
)
|
)
|
||||||
})),
|
})),
|
||||||
|
|
|
@ -2708,7 +2708,7 @@ impl Render for CollabPanel {
|
||||||
deferred(
|
deferred(
|
||||||
anchored()
|
anchored()
|
||||||
.position(*position)
|
.position(*position)
|
||||||
.anchor(gpui::AnchorCorner::TopLeft)
|
.anchor(gpui::Corner::TopLeft)
|
||||||
.child(menu.clone()),
|
.child(menu.clone()),
|
||||||
)
|
)
|
||||||
.with_priority(1)
|
.with_priority(1)
|
||||||
|
|
|
@ -409,7 +409,7 @@ impl PickerDelegate for ChannelModalDelegate {
|
||||||
Some(
|
Some(
|
||||||
deferred(
|
deferred(
|
||||||
anchored()
|
anchored()
|
||||||
.anchor(gpui::AnchorCorner::TopRight)
|
.anchor(gpui::Corner::TopRight)
|
||||||
.child(menu.clone()),
|
.child(menu.clone()),
|
||||||
)
|
)
|
||||||
.with_priority(1),
|
.with_priority(1),
|
||||||
|
|
|
@ -44,7 +44,7 @@ fn notification_window_options(
|
||||||
let notification_margin_height = px(-48.);
|
let notification_margin_height = px(-48.);
|
||||||
|
|
||||||
let bounds = gpui::Bounds::<Pixels> {
|
let bounds = gpui::Bounds::<Pixels> {
|
||||||
origin: screen.bounds().upper_right()
|
origin: screen.bounds().top_right()
|
||||||
- point(
|
- point(
|
||||||
size.width + notification_margin_width,
|
size.width + notification_margin_width,
|
||||||
notification_margin_height,
|
notification_margin_height,
|
||||||
|
|
|
@ -31,13 +31,13 @@ use file_icons::FileIcons;
|
||||||
use git::{blame::BlameEntry, diff::DiffHunkStatus, Oid};
|
use git::{blame::BlameEntry, diff::DiffHunkStatus, Oid};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
anchored, deferred, div, fill, outline, point, px, quad, relative, size, svg,
|
anchored, deferred, div, fill, outline, point, px, quad, relative, size, svg,
|
||||||
transparent_black, Action, AnchorCorner, AnyElement, AvailableSpace, Bounds, ClickEvent,
|
transparent_black, Action, AnyElement, AvailableSpace, Bounds, ClickEvent, ClipboardItem,
|
||||||
ClipboardItem, ContentMask, Corners, CursorStyle, DispatchPhase, Edges, Element,
|
ContentMask, Corner, Corners, CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler,
|
||||||
ElementInputHandler, Entity, FontId, GlobalElementId, HighlightStyle, Hitbox, Hsla,
|
Entity, FontId, GlobalElementId, HighlightStyle, Hitbox, Hsla, InteractiveElement, IntoElement,
|
||||||
InteractiveElement, IntoElement, Length, ModifiersChangedEvent, MouseButton, MouseDownEvent,
|
Length, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
|
||||||
MouseMoveEvent, MouseUpEvent, PaintQuad, ParentElement, Pixels, ScrollDelta, ScrollWheelEvent,
|
PaintQuad, ParentElement, Pixels, ScrollDelta, ScrollWheelEvent, ShapedLine, SharedString,
|
||||||
ShapedLine, SharedString, Size, StatefulInteractiveElement, Style, Styled, Subscription,
|
Size, StatefulInteractiveElement, Style, Styled, Subscription, TextRun, TextStyleRefinement,
|
||||||
TextRun, TextStyleRefinement, View, ViewContext, WeakView, WindowContext,
|
View, ViewContext, WeakView, WindowContext,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use language::{
|
use language::{
|
||||||
|
@ -706,7 +706,7 @@ impl EditorElement {
|
||||||
let mut scroll_delta = gpui::Point::<f32>::default();
|
let mut scroll_delta = gpui::Point::<f32>::default();
|
||||||
let vertical_margin = position_map.line_height.min(text_bounds.size.height / 3.0);
|
let vertical_margin = position_map.line_height.min(text_bounds.size.height / 3.0);
|
||||||
let top = text_bounds.origin.y + vertical_margin;
|
let top = text_bounds.origin.y + vertical_margin;
|
||||||
let bottom = text_bounds.lower_left().y - vertical_margin;
|
let bottom = text_bounds.bottom_left().y - vertical_margin;
|
||||||
if event.position.y < top {
|
if event.position.y < top {
|
||||||
scroll_delta.y = -scale_vertical_mouse_autoscroll_delta(top - event.position.y);
|
scroll_delta.y = -scale_vertical_mouse_autoscroll_delta(top - event.position.y);
|
||||||
}
|
}
|
||||||
|
@ -716,7 +716,7 @@ impl EditorElement {
|
||||||
|
|
||||||
let horizontal_margin = position_map.line_height.min(text_bounds.size.width / 3.0);
|
let horizontal_margin = position_map.line_height.min(text_bounds.size.width / 3.0);
|
||||||
let left = text_bounds.origin.x + horizontal_margin;
|
let left = text_bounds.origin.x + horizontal_margin;
|
||||||
let right = text_bounds.upper_right().x - horizontal_margin;
|
let right = text_bounds.top_right().x - horizontal_margin;
|
||||||
if event.position.x < left {
|
if event.position.x < left {
|
||||||
scroll_delta.x = -scale_horizontal_mouse_autoscroll_delta(left - event.position.x);
|
scroll_delta.x = -scale_horizontal_mouse_autoscroll_delta(left - event.position.x);
|
||||||
}
|
}
|
||||||
|
@ -1213,7 +1213,7 @@ impl EditorElement {
|
||||||
|
|
||||||
let track_bounds = Bounds::from_corners(
|
let track_bounds = Bounds::from_corners(
|
||||||
point(self.scrollbar_left(&bounds), bounds.origin.y),
|
point(self.scrollbar_left(&bounds), bounds.origin.y),
|
||||||
point(bounds.lower_right().x, bounds.lower_left().y),
|
point(bounds.bottom_right().x, bounds.bottom_left().y),
|
||||||
);
|
);
|
||||||
|
|
||||||
let settings = EditorSettings::get_global(cx);
|
let settings = EditorSettings::get_global(cx);
|
||||||
|
@ -2824,7 +2824,7 @@ impl EditorElement {
|
||||||
list_origin.x = (cx.viewport_size().width - list_width).max(Pixels::ZERO);
|
list_origin.x = (cx.viewport_size().width - list_width).max(Pixels::ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
if list_origin.y + list_height > text_hitbox.lower_right().y {
|
if list_origin.y + list_height > text_hitbox.bottom_right().y {
|
||||||
list_origin.y -= line_height + list_height;
|
list_origin.y -= line_height + list_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3067,7 +3067,7 @@ impl EditorElement {
|
||||||
anchored()
|
anchored()
|
||||||
.position(position)
|
.position(position)
|
||||||
.child(context_menu)
|
.child(context_menu)
|
||||||
.anchor(AnchorCorner::TopLeft)
|
.anchor(Corner::TopLeft)
|
||||||
.snap_to_window_with_margin(px(8.)),
|
.snap_to_window_with_margin(px(8.)),
|
||||||
)
|
)
|
||||||
.with_priority(1)
|
.with_priority(1)
|
||||||
|
@ -3132,7 +3132,7 @@ impl EditorElement {
|
||||||
for mut hover_popover in hover_popovers {
|
for mut hover_popover in hover_popovers {
|
||||||
let size = hover_popover.layout_as_root(AvailableSpace::min_size(), cx);
|
let size = hover_popover.layout_as_root(AvailableSpace::min_size(), cx);
|
||||||
let horizontal_offset =
|
let horizontal_offset =
|
||||||
(text_hitbox.upper_right().x - (hovered_point.x + size.width)).min(Pixels::ZERO);
|
(text_hitbox.top_right().x - (hovered_point.x + size.width)).min(Pixels::ZERO);
|
||||||
|
|
||||||
overall_height += HOVER_POPOVER_GAP + size.height;
|
overall_height += HOVER_POPOVER_GAP + size.height;
|
||||||
|
|
||||||
|
@ -4407,7 +4407,7 @@ impl EditorElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scrollbar_left(&self, bounds: &Bounds<Pixels>) -> Pixels {
|
fn scrollbar_left(&self, bounds: &Bounds<Pixels>) -> Pixels {
|
||||||
bounds.upper_right().x - self.style.scrollbar_width
|
bounds.top_right().x - self.style.scrollbar_width
|
||||||
}
|
}
|
||||||
|
|
||||||
fn column_pixels(&self, column: usize, cx: &WindowContext) -> Pixels {
|
fn column_pixels(&self, column: usize, cx: &WindowContext) -> Pixels {
|
||||||
|
@ -5488,7 +5488,7 @@ impl Element for EditorElement {
|
||||||
cx.insert_hitbox(gutter_bounds(bounds, gutter_dimensions), false);
|
cx.insert_hitbox(gutter_bounds(bounds, gutter_dimensions), false);
|
||||||
let text_hitbox = cx.insert_hitbox(
|
let text_hitbox = cx.insert_hitbox(
|
||||||
Bounds {
|
Bounds {
|
||||||
origin: gutter_hitbox.upper_right(),
|
origin: gutter_hitbox.top_right(),
|
||||||
size: size(text_width, bounds.size.height),
|
size: size(text_width, bounds.size.height),
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use collections::{HashMap, HashSet};
|
use collections::{HashMap, HashSet};
|
||||||
use git::diff::DiffHunkStatus;
|
use git::diff::DiffHunkStatus;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
Action, AnchorCorner, AppContext, CursorStyle, Hsla, Model, MouseButton, Subscription, Task,
|
Action, AppContext, Corner, CursorStyle, Hsla, Model, MouseButton, Subscription, Task, View,
|
||||||
View,
|
|
||||||
};
|
};
|
||||||
use language::{Buffer, BufferId, Point};
|
use language::{Buffer, BufferId, Point};
|
||||||
use multi_buffer::{
|
use multi_buffer::{
|
||||||
|
@ -743,7 +742,7 @@ impl Editor {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.anchor(AnchorCorner::TopRight)
|
.anchor(Corner::TopRight)
|
||||||
.with_handle(hunk_controls_menu_handle)
|
.with_handle(hunk_controls_menu_handle)
|
||||||
.menu(move |cx| {
|
.menu(move |cx| {
|
||||||
let focus = focus.clone();
|
let focus = focus.clone();
|
||||||
|
|
|
@ -1261,8 +1261,8 @@ impl PickerDelegate for FileFinderDelegate {
|
||||||
.child(
|
.child(
|
||||||
PopoverMenu::new("menu-popover")
|
PopoverMenu::new("menu-popover")
|
||||||
.with_handle(self.popover_menu_handle.clone())
|
.with_handle(self.popover_menu_handle.clone())
|
||||||
.attach(gpui::AnchorCorner::TopRight)
|
.attach(gpui::Corner::TopRight)
|
||||||
.anchor(gpui::AnchorCorner::BottomRight)
|
.anchor(gpui::Corner::BottomRight)
|
||||||
.trigger(
|
.trigger(
|
||||||
Button::new("actions-trigger", "Split Options")
|
Button::new("actions-trigger", "Split Options")
|
||||||
.selected_label_color(Color::Accent)
|
.selected_label_color(Color::Accent)
|
||||||
|
|
|
@ -218,13 +218,13 @@ impl Render for GradientViewer {
|
||||||
let height = square_bounds.size.height;
|
let height = square_bounds.size.height;
|
||||||
let horizontal_offset = height;
|
let horizontal_offset = height;
|
||||||
let vertical_offset = px(30.);
|
let vertical_offset = px(30.);
|
||||||
let mut path = gpui::Path::new(square_bounds.lower_left());
|
let mut path = gpui::Path::new(square_bounds.bottom_left());
|
||||||
path.line_to(square_bounds.origin + point(horizontal_offset, vertical_offset));
|
path.line_to(square_bounds.origin + point(horizontal_offset, vertical_offset));
|
||||||
path.line_to(
|
path.line_to(
|
||||||
square_bounds.upper_right() + point(-horizontal_offset, vertical_offset),
|
square_bounds.top_right() + point(-horizontal_offset, vertical_offset),
|
||||||
);
|
);
|
||||||
path.line_to(square_bounds.lower_right());
|
path.line_to(square_bounds.bottom_right());
|
||||||
path.line_to(square_bounds.lower_left());
|
path.line_to(square_bounds.bottom_left());
|
||||||
cx.paint_path(
|
cx.paint_path(
|
||||||
path,
|
path,
|
||||||
linear_gradient(
|
linear_gradient(
|
||||||
|
|
|
@ -49,17 +49,17 @@ impl PaintingViewer {
|
||||||
let height = square_bounds.size.height;
|
let height = square_bounds.size.height;
|
||||||
let horizontal_offset = height;
|
let horizontal_offset = height;
|
||||||
let vertical_offset = px(30.);
|
let vertical_offset = px(30.);
|
||||||
let mut path = Path::new(square_bounds.lower_left());
|
let mut path = Path::new(square_bounds.bottom_left());
|
||||||
path.curve_to(
|
path.curve_to(
|
||||||
square_bounds.origin + point(horizontal_offset, vertical_offset),
|
square_bounds.origin + point(horizontal_offset, vertical_offset),
|
||||||
square_bounds.origin + point(px(0.0), vertical_offset),
|
square_bounds.origin + point(px(0.0), vertical_offset),
|
||||||
);
|
);
|
||||||
path.line_to(square_bounds.upper_right() + point(-horizontal_offset, vertical_offset));
|
path.line_to(square_bounds.top_right() + point(-horizontal_offset, vertical_offset));
|
||||||
path.curve_to(
|
path.curve_to(
|
||||||
square_bounds.lower_right(),
|
square_bounds.bottom_right(),
|
||||||
square_bounds.upper_right() + point(px(0.0), vertical_offset),
|
square_bounds.top_right() + point(px(0.0), vertical_offset),
|
||||||
);
|
);
|
||||||
path.line_to(square_bounds.lower_left());
|
path.line_to(square_bounds.bottom_left());
|
||||||
lines.push(path);
|
lines.push(path);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -86,7 +86,7 @@ fn main() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let bounds = Bounds {
|
let bounds = Bounds {
|
||||||
origin: screen.bounds().upper_right()
|
origin: screen.bounds().top_right()
|
||||||
- point(size.width + margin_offset, -margin_offset),
|
- point(size.width + margin_offset, -margin_offset),
|
||||||
size,
|
size,
|
||||||
};
|
};
|
||||||
|
@ -101,7 +101,7 @@ fn main() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let bounds = Bounds {
|
let bounds = Bounds {
|
||||||
origin: screen.bounds().lower_left()
|
origin: screen.bounds().bottom_left()
|
||||||
- point(-margin_offset, size.height + margin_offset),
|
- point(-margin_offset, size.height + margin_offset),
|
||||||
size,
|
size,
|
||||||
};
|
};
|
||||||
|
@ -116,7 +116,7 @@ fn main() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let bounds = Bounds {
|
let bounds = Bounds {
|
||||||
origin: screen.bounds().lower_right()
|
origin: screen.bounds().bottom_right()
|
||||||
- point(size.width + margin_offset, size.height + margin_offset),
|
- point(size.width + margin_offset, size.height + margin_offset),
|
||||||
size,
|
size,
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,8 +2,8 @@ use smallvec::SmallVec;
|
||||||
use taffy::style::{Display, Position};
|
use taffy::style::{Display, Position};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
point, AnyElement, Bounds, Edges, Element, GlobalElementId, IntoElement, LayoutId,
|
point, AnyElement, Axis, Bounds, Corner, Edges, Element, GlobalElementId, IntoElement,
|
||||||
ParentElement, Pixels, Point, Size, Style, WindowContext,
|
LayoutId, ParentElement, Pixels, Point, Size, Style, WindowContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The state that the anchored element element uses to track its children.
|
/// The state that the anchored element element uses to track its children.
|
||||||
|
@ -15,7 +15,7 @@ pub struct AnchoredState {
|
||||||
/// will avoid overflowing the window bounds.
|
/// will avoid overflowing the window bounds.
|
||||||
pub struct Anchored {
|
pub struct Anchored {
|
||||||
children: SmallVec<[AnyElement; 2]>,
|
children: SmallVec<[AnyElement; 2]>,
|
||||||
anchor_corner: AnchorCorner,
|
anchor_corner: Corner,
|
||||||
fit_mode: AnchoredFitMode,
|
fit_mode: AnchoredFitMode,
|
||||||
anchor_position: Option<Point<Pixels>>,
|
anchor_position: Option<Point<Pixels>>,
|
||||||
position_mode: AnchoredPositionMode,
|
position_mode: AnchoredPositionMode,
|
||||||
|
@ -26,7 +26,7 @@ pub struct Anchored {
|
||||||
pub fn anchored() -> Anchored {
|
pub fn anchored() -> Anchored {
|
||||||
Anchored {
|
Anchored {
|
||||||
children: SmallVec::new(),
|
children: SmallVec::new(),
|
||||||
anchor_corner: AnchorCorner::TopLeft,
|
anchor_corner: Corner::TopLeft,
|
||||||
fit_mode: AnchoredFitMode::SwitchAnchor,
|
fit_mode: AnchoredFitMode::SwitchAnchor,
|
||||||
anchor_position: None,
|
anchor_position: None,
|
||||||
position_mode: AnchoredPositionMode::Window,
|
position_mode: AnchoredPositionMode::Window,
|
||||||
|
@ -35,7 +35,7 @@ pub fn anchored() -> Anchored {
|
||||||
|
|
||||||
impl Anchored {
|
impl Anchored {
|
||||||
/// Sets which corner of the anchored element should be anchored to the current position.
|
/// Sets which corner of the anchored element should be anchored to the current position.
|
||||||
pub fn anchor(mut self, anchor: AnchorCorner) -> Self {
|
pub fn anchor(mut self, anchor: Corner) -> Self {
|
||||||
self.anchor_corner = anchor;
|
self.anchor_corner = anchor;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ impl Element for Anchored {
|
||||||
for child_layout_id in &request_layout.child_layout_ids {
|
for child_layout_id in &request_layout.child_layout_ids {
|
||||||
let child_bounds = cx.layout_bounds(*child_layout_id);
|
let child_bounds = cx.layout_bounds(*child_layout_id);
|
||||||
child_min = child_min.min(&child_bounds.origin);
|
child_min = child_min.min(&child_bounds.origin);
|
||||||
child_max = child_max.max(&child_bounds.lower_right());
|
child_max = child_max.max(&child_bounds.bottom_right());
|
||||||
}
|
}
|
||||||
let size: Size<Pixels> = (child_max - child_min).into();
|
let size: Size<Pixels> = (child_max - child_min).into();
|
||||||
|
|
||||||
|
@ -140,19 +140,23 @@ impl Element for Anchored {
|
||||||
let mut anchor_corner = self.anchor_corner;
|
let mut anchor_corner = self.anchor_corner;
|
||||||
|
|
||||||
if desired.left() < limits.left() || desired.right() > limits.right() {
|
if desired.left() < limits.left() || desired.right() > limits.right() {
|
||||||
let switched = anchor_corner
|
let switched = Bounds::from_corner_and_size(
|
||||||
.switch_axis(Axis::Horizontal)
|
anchor_corner.other_side_corner_along(Axis::Horizontal),
|
||||||
.get_bounds(origin, size);
|
origin,
|
||||||
|
size,
|
||||||
|
);
|
||||||
if !(switched.left() < limits.left() || switched.right() > limits.right()) {
|
if !(switched.left() < limits.left() || switched.right() > limits.right()) {
|
||||||
anchor_corner = anchor_corner.switch_axis(Axis::Horizontal);
|
anchor_corner = anchor_corner.other_side_corner_along(Axis::Horizontal);
|
||||||
desired = switched
|
desired = switched
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if desired.top() < limits.top() || desired.bottom() > limits.bottom() {
|
if desired.top() < limits.top() || desired.bottom() > limits.bottom() {
|
||||||
let switched = anchor_corner
|
let switched = Bounds::from_corner_and_size(
|
||||||
.switch_axis(Axis::Vertical)
|
anchor_corner.other_side_corner_along(Axis::Vertical),
|
||||||
.get_bounds(origin, size);
|
origin,
|
||||||
|
size,
|
||||||
|
);
|
||||||
if !(switched.top() < limits.top() || switched.bottom() > limits.bottom()) {
|
if !(switched.top() < limits.top() || switched.bottom() > limits.bottom()) {
|
||||||
desired = switched;
|
desired = switched;
|
||||||
}
|
}
|
||||||
|
@ -214,11 +218,6 @@ impl IntoElement for Anchored {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Axis {
|
|
||||||
Horizontal,
|
|
||||||
Vertical,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Which algorithm to use when fitting the anchored element to be inside the window.
|
/// Which algorithm to use when fitting the anchored element to be inside the window.
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub enum AnchoredFitMode {
|
pub enum AnchoredFitMode {
|
||||||
|
@ -243,83 +242,25 @@ impl AnchoredPositionMode {
|
||||||
fn get_position_and_bounds(
|
fn get_position_and_bounds(
|
||||||
&self,
|
&self,
|
||||||
anchor_position: Option<Point<Pixels>>,
|
anchor_position: Option<Point<Pixels>>,
|
||||||
anchor_corner: AnchorCorner,
|
anchor_corner: Corner,
|
||||||
size: Size<Pixels>,
|
size: Size<Pixels>,
|
||||||
bounds: Bounds<Pixels>,
|
bounds: Bounds<Pixels>,
|
||||||
) -> (Point<Pixels>, Bounds<Pixels>) {
|
) -> (Point<Pixels>, Bounds<Pixels>) {
|
||||||
match self {
|
match self {
|
||||||
AnchoredPositionMode::Window => {
|
AnchoredPositionMode::Window => {
|
||||||
let anchor_position = anchor_position.unwrap_or(bounds.origin);
|
let anchor_position = anchor_position.unwrap_or(bounds.origin);
|
||||||
let bounds = anchor_corner.get_bounds(anchor_position, size);
|
let bounds = Bounds::from_corner_and_size(anchor_corner, anchor_position, size);
|
||||||
(anchor_position, bounds)
|
(anchor_position, bounds)
|
||||||
}
|
}
|
||||||
AnchoredPositionMode::Local => {
|
AnchoredPositionMode::Local => {
|
||||||
let anchor_position = anchor_position.unwrap_or_default();
|
let anchor_position = anchor_position.unwrap_or_default();
|
||||||
let bounds = anchor_corner.get_bounds(bounds.origin + anchor_position, size);
|
let bounds = Bounds::from_corner_and_size(
|
||||||
|
anchor_corner,
|
||||||
|
bounds.origin + anchor_position,
|
||||||
|
size,
|
||||||
|
);
|
||||||
(anchor_position, bounds)
|
(anchor_position, bounds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Which corner of the anchored element should be considered the anchor.
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub enum AnchorCorner {
|
|
||||||
/// The top left corner
|
|
||||||
TopLeft,
|
|
||||||
/// The top right corner
|
|
||||||
TopRight,
|
|
||||||
/// The bottom left corner
|
|
||||||
BottomLeft,
|
|
||||||
/// The bottom right corner
|
|
||||||
BottomRight,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AnchorCorner {
|
|
||||||
fn get_bounds(&self, origin: Point<Pixels>, size: Size<Pixels>) -> Bounds<Pixels> {
|
|
||||||
let origin = match self {
|
|
||||||
Self::TopLeft => origin,
|
|
||||||
Self::TopRight => Point {
|
|
||||||
x: origin.x - size.width,
|
|
||||||
y: origin.y,
|
|
||||||
},
|
|
||||||
Self::BottomLeft => Point {
|
|
||||||
x: origin.x,
|
|
||||||
y: origin.y - size.height,
|
|
||||||
},
|
|
||||||
Self::BottomRight => Point {
|
|
||||||
x: origin.x - size.width,
|
|
||||||
y: origin.y - size.height,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
Bounds { origin, size }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the point corresponding to this anchor corner in `bounds`.
|
|
||||||
pub fn corner(&self, bounds: Bounds<Pixels>) -> Point<Pixels> {
|
|
||||||
match self {
|
|
||||||
Self::TopLeft => bounds.origin,
|
|
||||||
Self::TopRight => bounds.upper_right(),
|
|
||||||
Self::BottomLeft => bounds.lower_left(),
|
|
||||||
Self::BottomRight => bounds.lower_right(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn switch_axis(self, axis: Axis) -> Self {
|
|
||||||
match axis {
|
|
||||||
Axis::Vertical => match self {
|
|
||||||
AnchorCorner::TopLeft => AnchorCorner::BottomLeft,
|
|
||||||
AnchorCorner::TopRight => AnchorCorner::BottomRight,
|
|
||||||
AnchorCorner::BottomLeft => AnchorCorner::TopLeft,
|
|
||||||
AnchorCorner::BottomRight => AnchorCorner::TopRight,
|
|
||||||
},
|
|
||||||
Axis::Horizontal => match self {
|
|
||||||
AnchorCorner::TopLeft => AnchorCorner::TopRight,
|
|
||||||
AnchorCorner::TopRight => AnchorCorner::TopLeft,
|
|
||||||
AnchorCorner::BottomLeft => AnchorCorner::BottomRight,
|
|
||||||
AnchorCorner::BottomRight => AnchorCorner::BottomLeft,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1193,7 +1193,7 @@ impl Element for Div {
|
||||||
for (ix, child_layout_id) in request_layout.child_layout_ids.iter().enumerate() {
|
for (ix, child_layout_id) in request_layout.child_layout_ids.iter().enumerate() {
|
||||||
let child_bounds = cx.layout_bounds(*child_layout_id);
|
let child_bounds = cx.layout_bounds(*child_layout_id);
|
||||||
child_min = child_min.min(&child_bounds.origin);
|
child_min = child_min.min(&child_bounds.origin);
|
||||||
child_max = child_max.max(&child_bounds.lower_right());
|
child_max = child_max.max(&child_bounds.bottom_right());
|
||||||
state.child_bounds.push(child_bounds);
|
state.child_bounds.push(child_bounds);
|
||||||
|
|
||||||
if let Some(requested) = requested.as_ref() {
|
if let Some(requested) = requested.as_ref() {
|
||||||
|
@ -1208,7 +1208,7 @@ impl Element for Div {
|
||||||
for child_layout_id in &request_layout.child_layout_ids {
|
for child_layout_id in &request_layout.child_layout_ids {
|
||||||
let child_bounds = cx.layout_bounds(*child_layout_id);
|
let child_bounds = cx.layout_bounds(*child_layout_id);
|
||||||
child_min = child_min.min(&child_bounds.origin);
|
child_min = child_min.min(&child_bounds.origin);
|
||||||
child_max = child_max.max(&child_bounds.lower_right());
|
child_max = child_max.max(&child_bounds.bottom_right());
|
||||||
}
|
}
|
||||||
(child_max - child_min).into()
|
(child_max - child_min).into()
|
||||||
};
|
};
|
||||||
|
|
|
@ -219,7 +219,7 @@ impl Element for UniformList {
|
||||||
|
|
||||||
let padded_bounds = Bounds::from_corners(
|
let padded_bounds = Bounds::from_corners(
|
||||||
bounds.origin + point(border.left + padding.left, border.top + padding.top),
|
bounds.origin + point(border.left + padding.left, border.top + padding.top),
|
||||||
bounds.lower_right()
|
bounds.bottom_right()
|
||||||
- point(border.right + padding.right, border.bottom + padding.bottom),
|
- point(border.right + padding.right, border.bottom + padding.bottom),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -261,7 +261,7 @@ impl Element for UniformList {
|
||||||
|
|
||||||
let padded_bounds = Bounds::from_corners(
|
let padded_bounds = Bounds::from_corners(
|
||||||
bounds.origin + point(border.left + padding.left, border.top),
|
bounds.origin + point(border.left + padding.left, border.top),
|
||||||
bounds.lower_right() - point(border.right + padding.right, border.bottom),
|
bounds.bottom_right() - point(border.right + padding.right, border.bottom),
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(handle) = self.scroll_handle.as_mut() {
|
if let Some(handle) = self.scroll_handle.as_mut() {
|
||||||
|
|
|
@ -694,7 +694,7 @@ impl Size<Length> {
|
||||||
/// Represents a rectangular area in a 2D space with an origin point and a size.
|
/// Represents a rectangular area in a 2D space with an origin point and a size.
|
||||||
///
|
///
|
||||||
/// The `Bounds` struct is generic over a type `T` which represents the type of the coordinate system.
|
/// The `Bounds` struct is generic over a type `T` which represents the type of the coordinate system.
|
||||||
/// The origin is represented as a `Point<T>` which defines the upper-left corner of the rectangle,
|
/// The origin is represented as a `Point<T>` which defines the top left corner of the rectangle,
|
||||||
/// and the size is represented as a `Size<T>` which defines the width and height of the rectangle.
|
/// and the size is represented as a `Size<T>` which defines the width and height of the rectangle.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
@ -757,16 +757,16 @@ impl<T> Bounds<T>
|
||||||
where
|
where
|
||||||
T: Clone + Debug + Sub<Output = T> + Default,
|
T: Clone + Debug + Sub<Output = T> + Default,
|
||||||
{
|
{
|
||||||
/// Constructs a `Bounds` from two corner points: the upper-left and lower-right corners.
|
/// Constructs a `Bounds` from two corner points: the top left and bottom right corners.
|
||||||
///
|
///
|
||||||
/// This function calculates the origin and size of the `Bounds` based on the provided corner points.
|
/// This function calculates the origin and size of the `Bounds` based on the provided corner points.
|
||||||
/// The origin is set to the upper-left corner, and the size is determined by the difference between
|
/// The origin is set to the top left corner, and the size is determined by the difference between
|
||||||
/// the x and y coordinates of the lower-right and upper-left points.
|
/// the x and y coordinates of the bottom right and top left points.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `upper_left` - A `Point<T>` representing the upper-left corner of the rectangle.
|
/// * `upper_left` - A `Point<T>` representing the top left corner of the rectangle.
|
||||||
/// * `lower_right` - A `Point<T>` representing the lower-right corner of the rectangle.
|
/// * `bottom_right` - A `Point<T>` representing the bottom right corner of the rectangle.
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
|
@ -777,25 +777,53 @@ where
|
||||||
/// ```
|
/// ```
|
||||||
/// # use gpui::{Bounds, Point};
|
/// # use gpui::{Bounds, Point};
|
||||||
/// let upper_left = Point { x: 0, y: 0 };
|
/// let upper_left = Point { x: 0, y: 0 };
|
||||||
/// let lower_right = Point { x: 10, y: 10 };
|
/// let bottom_right = Point { x: 10, y: 10 };
|
||||||
/// let bounds = Bounds::from_corners(upper_left, lower_right);
|
/// let bounds = Bounds::from_corners(upper_left, bottom_right);
|
||||||
///
|
///
|
||||||
/// assert_eq!(bounds.origin, upper_left);
|
/// assert_eq!(bounds.origin, upper_left);
|
||||||
/// assert_eq!(bounds.size.width, 10);
|
/// assert_eq!(bounds.size.width, 10);
|
||||||
/// assert_eq!(bounds.size.height, 10);
|
/// assert_eq!(bounds.size.height, 10);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn from_corners(upper_left: Point<T>, lower_right: Point<T>) -> Self {
|
pub fn from_corners(upper_left: Point<T>, bottom_right: Point<T>) -> Self {
|
||||||
let origin = Point {
|
let origin = Point {
|
||||||
x: upper_left.x.clone(),
|
x: upper_left.x.clone(),
|
||||||
y: upper_left.y.clone(),
|
y: upper_left.y.clone(),
|
||||||
};
|
};
|
||||||
let size = Size {
|
let size = Size {
|
||||||
width: lower_right.x - upper_left.x,
|
width: bottom_right.x - upper_left.x,
|
||||||
height: lower_right.y - upper_left.y,
|
height: bottom_right.y - upper_left.y,
|
||||||
};
|
};
|
||||||
Bounds { origin, size }
|
Bounds { origin, size }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructs a `Bounds` from a corner point and size.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use zed::{Bounds, Corner, Point};
|
||||||
|
/// todo!
|
||||||
|
/// ```
|
||||||
|
pub fn from_corner_and_size(corner: Corner, origin: Point<T>, size: Size<T>) -> Bounds<T> {
|
||||||
|
let origin = match corner {
|
||||||
|
Corner::TopLeft => origin,
|
||||||
|
Corner::TopRight => Point {
|
||||||
|
x: origin.x - size.width.clone(),
|
||||||
|
y: origin.y,
|
||||||
|
},
|
||||||
|
Corner::BottomLeft => Point {
|
||||||
|
x: origin.x,
|
||||||
|
y: origin.y - size.height.clone(),
|
||||||
|
},
|
||||||
|
Corner::BottomRight => Point {
|
||||||
|
x: origin.x - size.width.clone(),
|
||||||
|
y: origin.y - size.height.clone(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Bounds { origin, size }
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new `Bounds` with the specified origin and size.
|
/// Creates a new `Bounds` with the specified origin and size.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
|
@ -849,8 +877,8 @@ where
|
||||||
/// assert_eq!(bounds1.intersects(&bounds3), false); // Non-overlapping bounds
|
/// assert_eq!(bounds1.intersects(&bounds3), false); // Non-overlapping bounds
|
||||||
/// ```
|
/// ```
|
||||||
pub fn intersects(&self, other: &Bounds<T>) -> bool {
|
pub fn intersects(&self, other: &Bounds<T>) -> bool {
|
||||||
let my_lower_right = self.lower_right();
|
let my_lower_right = self.bottom_right();
|
||||||
let their_lower_right = other.lower_right();
|
let their_lower_right = other.bottom_right();
|
||||||
|
|
||||||
self.origin.x < their_lower_right.x
|
self.origin.x < their_lower_right.x
|
||||||
&& my_lower_right.x > other.origin.x
|
&& my_lower_right.x > other.origin.x
|
||||||
|
@ -996,8 +1024,8 @@ impl<T: Clone + Default + Debug + PartialOrd + Add<T, Output = T> + Sub<Output =
|
||||||
/// ```
|
/// ```
|
||||||
pub fn intersect(&self, other: &Self) -> Self {
|
pub fn intersect(&self, other: &Self) -> Self {
|
||||||
let upper_left = self.origin.max(&other.origin);
|
let upper_left = self.origin.max(&other.origin);
|
||||||
let lower_right = self.lower_right().min(&other.lower_right());
|
let bottom_right = self.bottom_right().min(&other.bottom_right());
|
||||||
Self::from_corners(upper_left, lower_right)
|
Self::from_corners(upper_left, bottom_right)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the union of two `Bounds`.
|
/// Computes the union of two `Bounds`.
|
||||||
|
@ -1035,7 +1063,7 @@ impl<T: Clone + Default + Debug + PartialOrd + Add<T, Output = T> + Sub<Output =
|
||||||
/// ```
|
/// ```
|
||||||
pub fn union(&self, other: &Self) -> Self {
|
pub fn union(&self, other: &Self) -> Self {
|
||||||
let top_left = self.origin.min(&other.origin);
|
let top_left = self.origin.min(&other.origin);
|
||||||
let bottom_right = self.lower_right().max(&other.lower_right());
|
let bottom_right = self.bottom_right().max(&other.bottom_right());
|
||||||
Bounds::from_corners(top_left, bottom_right)
|
Bounds::from_corners(top_left, bottom_right)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1123,11 +1151,11 @@ where
|
||||||
self.origin.x.clone() + self.size.width.clone()
|
self.origin.x.clone() + self.size.width.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the upper-right corner point of the bounds.
|
/// Returns the top right corner point of the bounds.
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
/// A `Point<T>` representing the upper-right corner of the bounds.
|
/// A `Point<T>` representing the top right corner of the bounds.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -1137,21 +1165,21 @@ where
|
||||||
/// origin: Point { x: 0, y: 0 },
|
/// origin: Point { x: 0, y: 0 },
|
||||||
/// size: Size { width: 10, height: 20 },
|
/// size: Size { width: 10, height: 20 },
|
||||||
/// };
|
/// };
|
||||||
/// let upper_right = bounds.upper_right();
|
/// let top_right = bounds.top_right();
|
||||||
/// assert_eq!(upper_right, Point { x: 10, y: 0 });
|
/// assert_eq!(top_right, Point { x: 10, y: 0 });
|
||||||
/// ```
|
/// ```
|
||||||
pub fn upper_right(&self) -> Point<T> {
|
pub fn top_right(&self) -> Point<T> {
|
||||||
Point {
|
Point {
|
||||||
x: self.origin.x.clone() + self.size.width.clone(),
|
x: self.origin.x.clone() + self.size.width.clone(),
|
||||||
y: self.origin.y.clone(),
|
y: self.origin.y.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the lower-right corner point of the bounds.
|
/// Returns the bottom right corner point of the bounds.
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
/// A `Point<T>` representing the lower-right corner of the bounds.
|
/// A `Point<T>` representing the bottom right corner of the bounds.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -1161,21 +1189,21 @@ where
|
||||||
/// origin: Point { x: 0, y: 0 },
|
/// origin: Point { x: 0, y: 0 },
|
||||||
/// size: Size { width: 10, height: 20 },
|
/// size: Size { width: 10, height: 20 },
|
||||||
/// };
|
/// };
|
||||||
/// let lower_right = bounds.lower_right();
|
/// let bottom_right = bounds.bottom_right();
|
||||||
/// assert_eq!(lower_right, Point { x: 10, y: 20 });
|
/// assert_eq!(bottom_right, Point { x: 10, y: 20 });
|
||||||
/// ```
|
/// ```
|
||||||
pub fn lower_right(&self) -> Point<T> {
|
pub fn bottom_right(&self) -> Point<T> {
|
||||||
Point {
|
Point {
|
||||||
x: self.origin.x.clone() + self.size.width.clone(),
|
x: self.origin.x.clone() + self.size.width.clone(),
|
||||||
y: self.origin.y.clone() + self.size.height.clone(),
|
y: self.origin.y.clone() + self.size.height.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the lower-left corner point of the bounds.
|
/// Returns the bottom left corner point of the bounds.
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
/// A `Point<T>` representing the lower-left corner of the bounds.
|
/// A `Point<T>` representing the bottom left corner of the bounds.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -1185,15 +1213,41 @@ where
|
||||||
/// origin: Point { x: 0, y: 0 },
|
/// origin: Point { x: 0, y: 0 },
|
||||||
/// size: Size { width: 10, height: 20 },
|
/// size: Size { width: 10, height: 20 },
|
||||||
/// };
|
/// };
|
||||||
/// let lower_left = bounds.lower_left();
|
/// let bottom_left = bounds.bottom_left();
|
||||||
/// assert_eq!(lower_left, Point { x: 0, y: 20 });
|
/// assert_eq!(bottom_left, Point { x: 0, y: 20 });
|
||||||
/// ```
|
/// ```
|
||||||
pub fn lower_left(&self) -> Point<T> {
|
pub fn bottom_left(&self) -> Point<T> {
|
||||||
Point {
|
Point {
|
||||||
x: self.origin.x.clone(),
|
x: self.origin.x.clone(),
|
||||||
y: self.origin.y.clone() + self.size.height.clone(),
|
y: self.origin.y.clone() + self.size.height.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the requested corner point of the bounds.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// A `Point<T>` representing the corner of the bounds requested by the parameter.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use zed::{Bounds, Corner, Point, Size};
|
||||||
|
/// let bounds = Bounds {
|
||||||
|
/// origin: Point { x: 0, y: 0 },
|
||||||
|
/// size: Size { width: 10, height: 20 },
|
||||||
|
/// };
|
||||||
|
/// let bottom_left = bounds.corner(Corner::BottomLeft);
|
||||||
|
/// assert_eq!(bottom_left, Point { x: 0, y: 20 });
|
||||||
|
/// ```
|
||||||
|
pub fn corner(&self, corner: Corner) -> Point<T> {
|
||||||
|
match corner {
|
||||||
|
Corner::TopLeft => self.origin.clone(),
|
||||||
|
Corner::TopRight => self.top_right(),
|
||||||
|
Corner::BottomLeft => self.bottom_left(),
|
||||||
|
Corner::BottomRight => self.bottom_right(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Bounds<T>
|
impl<T> Bounds<T>
|
||||||
|
@ -1861,6 +1915,64 @@ impl From<Pixels> for Edges<Pixels> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Identifies a corner of a 2d box.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum Corner {
|
||||||
|
/// The top left corner
|
||||||
|
TopLeft,
|
||||||
|
/// The top right corner
|
||||||
|
TopRight,
|
||||||
|
/// The bottom left corner
|
||||||
|
BottomLeft,
|
||||||
|
/// The bottom right corner
|
||||||
|
BottomRight,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Corner {
|
||||||
|
/// Returns the directly opposite corner.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use zed::Corner;
|
||||||
|
/// assert_eq!(Corner::TopLeft.opposite_corner(), Corner::BottomRight);
|
||||||
|
/// ```
|
||||||
|
pub fn opposite_corner(self) -> Self {
|
||||||
|
match self {
|
||||||
|
Corner::TopLeft => Corner::BottomRight,
|
||||||
|
Corner::TopRight => Corner::BottomLeft,
|
||||||
|
Corner::BottomLeft => Corner::TopRight,
|
||||||
|
Corner::BottomRight => Corner::TopLeft,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the corner across from this corner, moving along the specified axis.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use zed::Corner;
|
||||||
|
/// let result = Corner::TopLeft.other_side_corner_along(Axis::Horizontal);
|
||||||
|
/// assert_eq!(result, Corner::TopRight);
|
||||||
|
/// ```
|
||||||
|
pub fn other_side_corner_along(self, axis: Axis) -> Self {
|
||||||
|
match axis {
|
||||||
|
Axis::Vertical => match self {
|
||||||
|
Corner::TopLeft => Corner::BottomLeft,
|
||||||
|
Corner::TopRight => Corner::BottomRight,
|
||||||
|
Corner::BottomLeft => Corner::TopLeft,
|
||||||
|
Corner::BottomRight => Corner::TopRight,
|
||||||
|
},
|
||||||
|
Axis::Horizontal => match self {
|
||||||
|
Corner::TopLeft => Corner::TopRight,
|
||||||
|
Corner::TopRight => Corner::TopLeft,
|
||||||
|
Corner::BottomLeft => Corner::BottomRight,
|
||||||
|
Corner::BottomRight => Corner::BottomLeft,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents the corners of a box in a 2D space, such as border radius.
|
/// Represents the corners of a box in a 2D space, such as border radius.
|
||||||
///
|
///
|
||||||
/// Each field represents the size of the corner on one side of the box: `top_left`, `top_right`, `bottom_right`, and `bottom_left`.
|
/// Each field represents the size of the corner on one side of the box: `top_left`, `top_right`, `bottom_right`, and `bottom_left`.
|
||||||
|
@ -1914,6 +2026,33 @@ where
|
||||||
bottom_left: value,
|
bottom_left: value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the requested corner.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// A `Point<T>` representing the corner requested by the parameter.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use zed::{Corner, Corners};
|
||||||
|
/// let corners = Corners {
|
||||||
|
/// top_left: 1,
|
||||||
|
/// top_right: 2,
|
||||||
|
/// bottom_left: 3,
|
||||||
|
/// bottom_right: 4
|
||||||
|
/// };
|
||||||
|
/// assert_eq!(corners.corner(Corner::BottomLeft), 3);
|
||||||
|
/// ```
|
||||||
|
pub fn corner(&self, corner: Corner) -> T {
|
||||||
|
match corner {
|
||||||
|
Corner::TopLeft => self.top_left.clone(),
|
||||||
|
Corner::TopRight => self.top_right.clone(),
|
||||||
|
Corner::BottomLeft => self.bottom_left.clone(),
|
||||||
|
Corner::BottomRight => self.bottom_right.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Corners<AbsoluteLength> {
|
impl Corners<AbsoluteLength> {
|
||||||
|
|
|
@ -509,7 +509,7 @@ impl Style {
|
||||||
} => None,
|
} => None,
|
||||||
_ => {
|
_ => {
|
||||||
let mut min = bounds.origin;
|
let mut min = bounds.origin;
|
||||||
let mut max = bounds.lower_right();
|
let mut max = bounds.bottom_right();
|
||||||
|
|
||||||
if self
|
if self
|
||||||
.border_color
|
.border_color
|
||||||
|
@ -530,12 +530,12 @@ impl Style {
|
||||||
// x visible, y hidden
|
// x visible, y hidden
|
||||||
(true, false) => Bounds::from_corners(
|
(true, false) => Bounds::from_corners(
|
||||||
point(min.x, bounds.origin.y),
|
point(min.x, bounds.origin.y),
|
||||||
point(max.x, bounds.lower_right().y),
|
point(max.x, bounds.bottom_right().y),
|
||||||
),
|
),
|
||||||
// x hidden, y visible
|
// x hidden, y visible
|
||||||
(false, true) => Bounds::from_corners(
|
(false, true) => Bounds::from_corners(
|
||||||
point(bounds.origin.x, min.y),
|
point(bounds.origin.x, min.y),
|
||||||
point(bounds.lower_right().x, max.y),
|
point(bounds.bottom_right().x, max.y),
|
||||||
),
|
),
|
||||||
// both hidden
|
// both hidden
|
||||||
(false, false) => Bounds::from_corners(min, max),
|
(false, false) => Bounds::from_corners(min, max),
|
||||||
|
@ -604,19 +604,19 @@ impl Style {
|
||||||
|
|
||||||
let top_bounds = Bounds::from_corners(
|
let top_bounds = Bounds::from_corners(
|
||||||
bounds.origin,
|
bounds.origin,
|
||||||
bounds.upper_right() + point(Pixels::ZERO, max_border_width.max(max_corner_radius)),
|
bounds.top_right() + point(Pixels::ZERO, max_border_width.max(max_corner_radius)),
|
||||||
);
|
);
|
||||||
let bottom_bounds = Bounds::from_corners(
|
let bottom_bounds = Bounds::from_corners(
|
||||||
bounds.lower_left() - point(Pixels::ZERO, max_border_width.max(max_corner_radius)),
|
bounds.bottom_left() - point(Pixels::ZERO, max_border_width.max(max_corner_radius)),
|
||||||
bounds.lower_right(),
|
bounds.bottom_right(),
|
||||||
);
|
);
|
||||||
let left_bounds = Bounds::from_corners(
|
let left_bounds = Bounds::from_corners(
|
||||||
top_bounds.lower_left(),
|
top_bounds.bottom_left(),
|
||||||
bottom_bounds.origin + point(max_border_width, Pixels::ZERO),
|
bottom_bounds.origin + point(max_border_width, Pixels::ZERO),
|
||||||
);
|
);
|
||||||
let right_bounds = Bounds::from_corners(
|
let right_bounds = Bounds::from_corners(
|
||||||
top_bounds.lower_right() - point(max_border_width, Pixels::ZERO),
|
top_bounds.bottom_right() - point(max_border_width, Pixels::ZERO),
|
||||||
bottom_bounds.upper_right(),
|
bottom_bounds.top_right(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut background = self.border_color.unwrap_or_default();
|
let mut background = self.border_color.unwrap_or_default();
|
||||||
|
|
|
@ -4,7 +4,7 @@ use editor::{scroll::Autoscroll, Editor};
|
||||||
use feature_flags::{FeatureFlagAppExt, ZetaFeatureFlag};
|
use feature_flags::{FeatureFlagAppExt, ZetaFeatureFlag};
|
||||||
use fs::Fs;
|
use fs::Fs;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, Action, AnchorCorner, AppContext, AsyncWindowContext, Entity, IntoElement,
|
actions, div, Action, AppContext, AsyncWindowContext, Corner, Entity, IntoElement,
|
||||||
ParentElement, Render, Subscription, View, ViewContext, WeakView, WindowContext,
|
ParentElement, Render, Subscription, View, ViewContext, WeakView, WindowContext,
|
||||||
};
|
};
|
||||||
use language::{
|
use language::{
|
||||||
|
@ -123,7 +123,7 @@ impl Render for InlineCompletionButton {
|
||||||
_ => this.update(cx, |this, cx| this.build_copilot_start_menu(cx)),
|
_ => this.update(cx, |this, cx| this.build_copilot_start_menu(cx)),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.anchor(AnchorCorner::BottomRight)
|
.anchor(Corner::BottomRight)
|
||||||
.trigger(
|
.trigger(
|
||||||
IconButton::new("copilot-icon", icon)
|
IconButton::new("copilot-icon", icon)
|
||||||
.tooltip(|cx| Tooltip::text("GitHub Copilot", cx)),
|
.tooltip(|cx| Tooltip::text("GitHub Copilot", cx)),
|
||||||
|
@ -191,7 +191,7 @@ impl Render for InlineCompletionButton {
|
||||||
),
|
),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.anchor(AnchorCorner::BottomRight)
|
.anchor(Corner::BottomRight)
|
||||||
.trigger(
|
.trigger(
|
||||||
IconButton::new("supermaven-icon", icon)
|
IconButton::new("supermaven-icon", icon)
|
||||||
.tooltip(move |cx| Tooltip::text(tooltip_text.clone(), cx)),
|
.tooltip(move |cx| Tooltip::text(tooltip_text.clone(), cx)),
|
||||||
|
|
|
@ -107,7 +107,7 @@ impl<T: PopoverTrigger> RenderOnce for LanguageModelSelectorPopoverMenu<T> {
|
||||||
PopoverMenu::new("model-switcher")
|
PopoverMenu::new("model-switcher")
|
||||||
.menu(move |_cx| Some(language_model_selector.clone()))
|
.menu(move |_cx| Some(language_model_selector.clone()))
|
||||||
.trigger(self.trigger)
|
.trigger(self.trigger)
|
||||||
.attach(gpui::AnchorCorner::BottomLeft)
|
.attach(gpui::Corner::BottomLeft)
|
||||||
.when_some(self.handle.clone(), |menu, handle| menu.with_handle(handle))
|
.when_some(self.handle.clone(), |menu, handle| menu.with_handle(handle))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use copilot::Copilot;
|
||||||
use editor::{actions::MoveToEnd, Editor, EditorEvent};
|
use editor::{actions::MoveToEnd, Editor, EditorEvent};
|
||||||
use futures::{channel::mpsc, StreamExt};
|
use futures::{channel::mpsc, StreamExt};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, AnchorCorner, AppContext, Context, EventEmitter, FocusHandle, FocusableView,
|
actions, div, AppContext, Context, Corner, EventEmitter, FocusHandle, FocusableView,
|
||||||
IntoElement, Model, ModelContext, ParentElement, Render, Styled, Subscription, View,
|
IntoElement, Model, ModelContext, ParentElement, Render, Styled, Subscription, View,
|
||||||
ViewContext, VisualContext, WeakModel, WindowContext,
|
ViewContext, VisualContext, WeakModel, WindowContext,
|
||||||
};
|
};
|
||||||
|
@ -1158,7 +1158,7 @@ impl Render for LspLogToolbarItemView {
|
||||||
.collect();
|
.collect();
|
||||||
let log_toolbar_view = cx.view().clone();
|
let log_toolbar_view = cx.view().clone();
|
||||||
let lsp_menu = PopoverMenu::new("LspLogView")
|
let lsp_menu = PopoverMenu::new("LspLogView")
|
||||||
.anchor(AnchorCorner::TopLeft)
|
.anchor(Corner::TopLeft)
|
||||||
.trigger(Button::new(
|
.trigger(Button::new(
|
||||||
"language_server_menu_header",
|
"language_server_menu_header",
|
||||||
current_server
|
current_server
|
||||||
|
@ -1214,7 +1214,7 @@ impl Render for LspLogToolbarItemView {
|
||||||
let rpc_trace_enabled = server.rpc_trace_enabled;
|
let rpc_trace_enabled = server.rpc_trace_enabled;
|
||||||
let log_view = log_view.clone();
|
let log_view = log_view.clone();
|
||||||
PopoverMenu::new("LspViewSelector")
|
PopoverMenu::new("LspViewSelector")
|
||||||
.anchor(AnchorCorner::TopLeft)
|
.anchor(Corner::TopLeft)
|
||||||
.trigger(Button::new(
|
.trigger(Button::new(
|
||||||
"language_server_menu_header",
|
"language_server_menu_header",
|
||||||
server.selected_entry.label(),
|
server.selected_entry.label(),
|
||||||
|
@ -1301,7 +1301,7 @@ impl Render for LspLogToolbarItemView {
|
||||||
let log_view = log_view.clone();
|
let log_view = log_view.clone();
|
||||||
div().child(
|
div().child(
|
||||||
PopoverMenu::new("lsp-trace-level-menu")
|
PopoverMenu::new("lsp-trace-level-menu")
|
||||||
.anchor(AnchorCorner::TopLeft)
|
.anchor(Corner::TopLeft)
|
||||||
.trigger(Button::new(
|
.trigger(Button::new(
|
||||||
"language_server_trace_level_selector",
|
"language_server_trace_level_selector",
|
||||||
"Trace level",
|
"Trace level",
|
||||||
|
@ -1359,7 +1359,7 @@ impl Render for LspLogToolbarItemView {
|
||||||
let log_view = log_view.clone();
|
let log_view = log_view.clone();
|
||||||
div().child(
|
div().child(
|
||||||
PopoverMenu::new("lsp-log-level-menu")
|
PopoverMenu::new("lsp-log-level-menu")
|
||||||
.anchor(AnchorCorner::TopLeft)
|
.anchor(Corner::TopLeft)
|
||||||
.trigger(Button::new(
|
.trigger(Button::new(
|
||||||
"language_server_log_level_selector",
|
"language_server_log_level_selector",
|
||||||
"Log level",
|
"Log level",
|
||||||
|
|
|
@ -4257,7 +4257,7 @@ impl OutlinePanel {
|
||||||
deferred(
|
deferred(
|
||||||
anchored()
|
anchored()
|
||||||
.position(*position)
|
.position(*position)
|
||||||
.anchor(gpui::AnchorCorner::TopLeft)
|
.anchor(gpui::Corner::TopLeft)
|
||||||
.child(menu.clone()),
|
.child(menu.clone()),
|
||||||
)
|
)
|
||||||
.with_priority(1)
|
.with_priority(1)
|
||||||
|
|
|
@ -4102,7 +4102,7 @@ impl Render for ProjectPanel {
|
||||||
deferred(
|
deferred(
|
||||||
anchored()
|
anchored()
|
||||||
.position(*position)
|
.position(*position)
|
||||||
.anchor(gpui::AnchorCorner::TopLeft)
|
.anchor(gpui::Corner::TopLeft)
|
||||||
.child(menu.clone()),
|
.child(menu.clone()),
|
||||||
)
|
)
|
||||||
.with_priority(1)
|
.with_priority(1)
|
||||||
|
|
|
@ -253,7 +253,7 @@ impl<T: PopoverTrigger> RenderOnce for KernelSelector<T> {
|
||||||
PopoverMenu::new("kernel-switcher")
|
PopoverMenu::new("kernel-switcher")
|
||||||
.menu(move |_cx| Some(picker_view.clone()))
|
.menu(move |_cx| Some(picker_view.clone()))
|
||||||
.trigger(self.trigger)
|
.trigger(self.trigger)
|
||||||
.attach(gpui::AnchorCorner::BottomLeft)
|
.attach(gpui::Corner::BottomLeft)
|
||||||
.when_some(self.handle, |menu, handle| menu.with_handle(handle))
|
.when_some(self.handle, |menu, handle| menu.with_handle(handle))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1461,7 +1461,7 @@ impl Terminal {
|
||||||
fn drag_line_delta(&self, e: &MouseMoveEvent, region: Bounds<Pixels>) -> Option<Pixels> {
|
fn drag_line_delta(&self, e: &MouseMoveEvent, region: Bounds<Pixels>) -> Option<Pixels> {
|
||||||
//TODO: Why do these need to be doubled? Probably the same problem that the IME has
|
//TODO: Why do these need to be doubled? Probably the same problem that the IME has
|
||||||
let top = region.origin.y + (self.last_content.size.line_height * 2.);
|
let top = region.origin.y + (self.last_content.size.line_height * 2.);
|
||||||
let bottom = region.lower_left().y - (self.last_content.size.line_height * 2.);
|
let bottom = region.bottom_left().y - (self.last_content.size.line_height * 2.);
|
||||||
let scroll_delta = if e.position.y < top {
|
let scroll_delta = if e.position.y < top {
|
||||||
(top - e.position.y).pow(1.1)
|
(top - e.position.y).pow(1.1)
|
||||||
} else if e.position.y > bottom {
|
} else if e.position.y > bottom {
|
||||||
|
|
|
@ -12,7 +12,7 @@ use collections::HashMap;
|
||||||
use db::kvp::KEY_VALUE_STORE;
|
use db::kvp::KEY_VALUE_STORE;
|
||||||
use futures::future::join_all;
|
use futures::future::join_all;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, Action, AnchorCorner, AnyView, AppContext, AsyncWindowContext, Entity, EventEmitter,
|
actions, Action, AnyView, AppContext, AsyncWindowContext, Corner, Entity, EventEmitter,
|
||||||
ExternalPaths, FocusHandle, FocusableView, IntoElement, Model, ParentElement, Pixels, Render,
|
ExternalPaths, FocusHandle, FocusableView, IntoElement, Model, ParentElement, Pixels, Render,
|
||||||
Styled, Task, View, ViewContext, VisualContext, WeakView, WindowContext,
|
Styled, Task, View, ViewContext, VisualContext, WeakView, WindowContext,
|
||||||
};
|
};
|
||||||
|
@ -141,7 +141,7 @@ impl TerminalPanel {
|
||||||
.icon_size(IconSize::Small)
|
.icon_size(IconSize::Small)
|
||||||
.tooltip(|cx| Tooltip::text("New…", cx)),
|
.tooltip(|cx| Tooltip::text("New…", cx)),
|
||||||
)
|
)
|
||||||
.anchor(AnchorCorner::TopRight)
|
.anchor(Corner::TopRight)
|
||||||
.with_handle(pane.new_item_context_menu_handle.clone())
|
.with_handle(pane.new_item_context_menu_handle.clone())
|
||||||
.menu(move |cx| {
|
.menu(move |cx| {
|
||||||
let focus_handle = focus_handle.clone();
|
let focus_handle = focus_handle.clone();
|
||||||
|
@ -171,7 +171,7 @@ impl TerminalPanel {
|
||||||
.icon_size(IconSize::Small)
|
.icon_size(IconSize::Small)
|
||||||
.tooltip(|cx| Tooltip::text("Split Pane", cx)),
|
.tooltip(|cx| Tooltip::text("Split Pane", cx)),
|
||||||
)
|
)
|
||||||
.anchor(AnchorCorner::TopRight)
|
.anchor(Corner::TopRight)
|
||||||
.with_handle(pane.split_item_context_menu_handle.clone())
|
.with_handle(pane.split_item_context_menu_handle.clone())
|
||||||
.menu({
|
.menu({
|
||||||
let split_context = split_context.clone();
|
let split_context = split_context.clone();
|
||||||
|
|
|
@ -987,7 +987,7 @@ impl Render for TerminalView {
|
||||||
deferred(
|
deferred(
|
||||||
anchored()
|
anchored()
|
||||||
.position(*position)
|
.position(*position)
|
||||||
.anchor(gpui::AnchorCorner::TopLeft)
|
.anchor(gpui::Corner::TopLeft)
|
||||||
.child(menu.clone()),
|
.child(menu.clone()),
|
||||||
)
|
)
|
||||||
.with_priority(1)
|
.with_priority(1)
|
||||||
|
|
|
@ -73,17 +73,17 @@ fn render_color_ribbon(color: Hsla) -> impl Element {
|
||||||
let height = bounds.size.height;
|
let height = bounds.size.height;
|
||||||
let horizontal_offset = height;
|
let horizontal_offset = height;
|
||||||
let vertical_offset = px(height.0 / 2.0);
|
let vertical_offset = px(height.0 / 2.0);
|
||||||
let mut path = Path::new(bounds.lower_left());
|
let mut path = Path::new(bounds.bottom_left());
|
||||||
path.curve_to(
|
path.curve_to(
|
||||||
bounds.origin + point(horizontal_offset, vertical_offset),
|
bounds.origin + point(horizontal_offset, vertical_offset),
|
||||||
bounds.origin + point(px(0.0), vertical_offset),
|
bounds.origin + point(px(0.0), vertical_offset),
|
||||||
);
|
);
|
||||||
path.line_to(bounds.upper_right() + point(-horizontal_offset, vertical_offset));
|
path.line_to(bounds.top_right() + point(-horizontal_offset, vertical_offset));
|
||||||
path.curve_to(
|
path.curve_to(
|
||||||
bounds.lower_right(),
|
bounds.bottom_right(),
|
||||||
bounds.upper_right() + point(px(0.0), vertical_offset),
|
bounds.top_right() + point(px(0.0), vertical_offset),
|
||||||
);
|
);
|
||||||
path.line_to(bounds.lower_left());
|
path.line_to(bounds.bottom_left());
|
||||||
cx.paint_path(path, color);
|
cx.paint_path(path, color);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -615,7 +615,7 @@ impl TitleBar {
|
||||||
.style(ButtonStyle::Subtle)
|
.style(ButtonStyle::Subtle)
|
||||||
.tooltip(move |cx| Tooltip::text("Toggle User Menu", cx)),
|
.tooltip(move |cx| Tooltip::text("Toggle User Menu", cx)),
|
||||||
)
|
)
|
||||||
.anchor(gpui::AnchorCorner::TopRight)
|
.anchor(gpui::Corner::TopRight)
|
||||||
} else {
|
} else {
|
||||||
PopoverMenu::new("user-menu")
|
PopoverMenu::new("user-menu")
|
||||||
.menu(|cx| {
|
.menu(|cx| {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#![allow(missing_docs)]
|
#![allow(missing_docs)]
|
||||||
use gpui::{AnchorCorner, ClickEvent, CursorStyle, MouseButton, View};
|
use gpui::{ClickEvent, Corner, CursorStyle, MouseButton, View};
|
||||||
|
|
||||||
use crate::{prelude::*, ContextMenu, PopoverMenu};
|
use crate::{prelude::*, ContextMenu, PopoverMenu};
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ impl RenderOnce for DropdownMenu {
|
||||||
.full_width(self.full_width)
|
.full_width(self.full_width)
|
||||||
.menu(move |_cx| Some(self.menu.clone()))
|
.menu(move |_cx| Some(self.menu.clone()))
|
||||||
.trigger(DropdownMenuTrigger::new(self.label).full_width(self.full_width))
|
.trigger(DropdownMenuTrigger::new(self.label).full_width(self.full_width))
|
||||||
.attach(AnchorCorner::BottomLeft)
|
.attach(Corner::BottomLeft)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
anchored, deferred, div, point, prelude::FluentBuilder, px, size, AnchorCorner, AnyElement,
|
anchored, deferred, div, point, prelude::FluentBuilder, px, size, AnyElement, Bounds, Corner,
|
||||||
Bounds, DismissEvent, DispatchPhase, Element, ElementId, GlobalElementId, HitboxId,
|
DismissEvent, DispatchPhase, Element, ElementId, GlobalElementId, HitboxId, InteractiveElement,
|
||||||
InteractiveElement, IntoElement, LayoutId, Length, ManagedView, MouseDownEvent, ParentElement,
|
IntoElement, LayoutId, Length, ManagedView, MouseDownEvent, ParentElement, Pixels, Point,
|
||||||
Pixels, Point, Style, View, VisualContext, WindowContext,
|
Style, View, VisualContext, WindowContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
@ -89,8 +89,8 @@ pub struct PopoverMenu<M: ManagedView> {
|
||||||
>,
|
>,
|
||||||
>,
|
>,
|
||||||
menu_builder: Option<Rc<dyn Fn(&mut WindowContext) -> Option<View<M>> + 'static>>,
|
menu_builder: Option<Rc<dyn Fn(&mut WindowContext) -> Option<View<M>> + 'static>>,
|
||||||
anchor: AnchorCorner,
|
anchor: Corner,
|
||||||
attach: Option<AnchorCorner>,
|
attach: Option<Corner>,
|
||||||
offset: Option<Point<Pixels>>,
|
offset: Option<Point<Pixels>>,
|
||||||
trigger_handle: Option<PopoverMenuHandle<M>>,
|
trigger_handle: Option<PopoverMenuHandle<M>>,
|
||||||
full_width: bool,
|
full_width: bool,
|
||||||
|
@ -103,7 +103,7 @@ impl<M: ManagedView> PopoverMenu<M> {
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
child_builder: None,
|
child_builder: None,
|
||||||
menu_builder: None,
|
menu_builder: None,
|
||||||
anchor: AnchorCorner::TopLeft,
|
anchor: Corner::TopLeft,
|
||||||
attach: None,
|
attach: None,
|
||||||
offset: None,
|
offset: None,
|
||||||
trigger_handle: None,
|
trigger_handle: None,
|
||||||
|
@ -140,13 +140,13 @@ impl<M: ManagedView> PopoverMenu<M> {
|
||||||
|
|
||||||
/// anchor defines which corner of the menu to anchor to the attachment point
|
/// anchor defines which corner of the menu to anchor to the attachment point
|
||||||
/// (by default the cursor position, but see attach)
|
/// (by default the cursor position, but see attach)
|
||||||
pub fn anchor(mut self, anchor: AnchorCorner) -> Self {
|
pub fn anchor(mut self, anchor: Corner) -> Self {
|
||||||
self.anchor = anchor;
|
self.anchor = anchor;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// attach defines which corner of the handle to attach the menu's anchor to
|
/// attach defines which corner of the handle to attach the menu's anchor to
|
||||||
pub fn attach(mut self, attach: AnchorCorner) -> Self {
|
pub fn attach(mut self, attach: Corner) -> Self {
|
||||||
self.attach = Some(attach);
|
self.attach = Some(attach);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -157,12 +157,12 @@ impl<M: ManagedView> PopoverMenu<M> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolved_attach(&self) -> AnchorCorner {
|
fn resolved_attach(&self) -> Corner {
|
||||||
self.attach.unwrap_or(match self.anchor {
|
self.attach.unwrap_or(match self.anchor {
|
||||||
AnchorCorner::TopLeft => AnchorCorner::BottomLeft,
|
Corner::TopLeft => Corner::BottomLeft,
|
||||||
AnchorCorner::TopRight => AnchorCorner::BottomRight,
|
Corner::TopRight => Corner::BottomRight,
|
||||||
AnchorCorner::BottomLeft => AnchorCorner::TopLeft,
|
Corner::BottomLeft => Corner::TopLeft,
|
||||||
AnchorCorner::BottomRight => AnchorCorner::TopRight,
|
Corner::BottomRight => Corner::TopRight,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,8 +171,8 @@ impl<M: ManagedView> PopoverMenu<M> {
|
||||||
// Default offset = 4px padding + 1px border
|
// Default offset = 4px padding + 1px border
|
||||||
let offset = rems_from_px(5.) * cx.rem_size();
|
let offset = rems_from_px(5.) * cx.rem_size();
|
||||||
match self.anchor {
|
match self.anchor {
|
||||||
AnchorCorner::TopRight | AnchorCorner::BottomRight => point(offset, px(0.)),
|
Corner::TopRight | Corner::BottomRight => point(offset, px(0.)),
|
||||||
AnchorCorner::TopLeft | AnchorCorner::BottomLeft => point(-offset, px(0.)),
|
Corner::TopLeft | Corner::BottomLeft => point(-offset, px(0.)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -259,7 +259,7 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
|
||||||
.anchor(self.anchor);
|
.anchor(self.anchor);
|
||||||
if let Some(child_bounds) = element_state.child_bounds {
|
if let Some(child_bounds) = element_state.child_bounds {
|
||||||
anchored = anchored.position(
|
anchored = anchored.position(
|
||||||
self.resolved_attach().corner(child_bounds) + self.resolved_offset(cx),
|
child_bounds.corner(self.resolved_attach()) + self.resolved_offset(cx),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let mut element = deferred(anchored.child(div().occlude().child(menu.clone())))
|
let mut element = deferred(anchored.child(div().occlude().child(menu.clone())))
|
||||||
|
|
|
@ -3,18 +3,17 @@
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
anchored, deferred, div, px, AnchorCorner, AnyElement, Bounds, DismissEvent, DispatchPhase,
|
anchored, deferred, div, px, AnyElement, Bounds, Corner, DismissEvent, DispatchPhase, Element,
|
||||||
Element, ElementId, GlobalElementId, Hitbox, InteractiveElement, IntoElement, LayoutId,
|
ElementId, GlobalElementId, Hitbox, InteractiveElement, IntoElement, LayoutId, ManagedView,
|
||||||
ManagedView, MouseButton, MouseDownEvent, ParentElement, Pixels, Point, View, VisualContext,
|
MouseButton, MouseDownEvent, ParentElement, Pixels, Point, View, VisualContext, WindowContext,
|
||||||
WindowContext,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct RightClickMenu<M: ManagedView> {
|
pub struct RightClickMenu<M: ManagedView> {
|
||||||
id: ElementId,
|
id: ElementId,
|
||||||
child_builder: Option<Box<dyn FnOnce(bool) -> AnyElement + 'static>>,
|
child_builder: Option<Box<dyn FnOnce(bool) -> AnyElement + 'static>>,
|
||||||
menu_builder: Option<Rc<dyn Fn(&mut WindowContext) -> View<M> + 'static>>,
|
menu_builder: Option<Rc<dyn Fn(&mut WindowContext) -> View<M> + 'static>>,
|
||||||
anchor: Option<AnchorCorner>,
|
anchor: Option<Corner>,
|
||||||
attach: Option<AnchorCorner>,
|
attach: Option<Corner>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M: ManagedView> RightClickMenu<M> {
|
impl<M: ManagedView> RightClickMenu<M> {
|
||||||
|
@ -30,13 +29,13 @@ impl<M: ManagedView> RightClickMenu<M> {
|
||||||
|
|
||||||
/// anchor defines which corner of the menu to anchor to the attachment point
|
/// anchor defines which corner of the menu to anchor to the attachment point
|
||||||
/// (by default the cursor position, but see attach)
|
/// (by default the cursor position, but see attach)
|
||||||
pub fn anchor(mut self, anchor: AnchorCorner) -> Self {
|
pub fn anchor(mut self, anchor: Corner) -> Self {
|
||||||
self.anchor = Some(anchor);
|
self.anchor = Some(anchor);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// attach defines which corner of the handle to attach the menu's anchor to
|
/// attach defines which corner of the handle to attach the menu's anchor to
|
||||||
pub fn attach(mut self, attach: AnchorCorner) -> Self {
|
pub fn attach(mut self, attach: Corner) -> Self {
|
||||||
self.attach = Some(attach);
|
self.attach = Some(attach);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -238,7 +237,7 @@ impl<M: ManagedView> Element for RightClickMenu<M> {
|
||||||
*menu.borrow_mut() = Some(new_menu);
|
*menu.borrow_mut() = Some(new_menu);
|
||||||
*position.borrow_mut() = if let Some(child_bounds) = child_bounds {
|
*position.borrow_mut() = if let Some(child_bounds) = child_bounds {
|
||||||
if let Some(attach) = attach {
|
if let Some(attach) = attach {
|
||||||
attach.corner(child_bounds)
|
child_bounds.corner(attach)
|
||||||
} else {
|
} else {
|
||||||
cx.mouse_position()
|
cx.mouse_position()
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,12 +236,12 @@ impl Element for Scrollbar {
|
||||||
let padded_bounds = if is_vertical {
|
let padded_bounds = if is_vertical {
|
||||||
Bounds::from_corners(
|
Bounds::from_corners(
|
||||||
bounds.origin + point(Pixels::ZERO, extra_padding),
|
bounds.origin + point(Pixels::ZERO, extra_padding),
|
||||||
bounds.lower_right() - point(Pixels::ZERO, extra_padding * 3),
|
bounds.bottom_right() - point(Pixels::ZERO, extra_padding * 3),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Bounds::from_corners(
|
Bounds::from_corners(
|
||||||
bounds.origin + point(extra_padding, Pixels::ZERO),
|
bounds.origin + point(extra_padding, Pixels::ZERO),
|
||||||
bounds.lower_right() - point(extra_padding * 3, Pixels::ZERO),
|
bounds.bottom_right() - point(extra_padding * 3, Pixels::ZERO),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use gpui::{actions, AnchorCorner, Render, View};
|
use gpui::{actions, Corner, Render, View};
|
||||||
use story::Story;
|
use story::Story;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
@ -47,8 +47,8 @@ impl Render for ContextMenuStory {
|
||||||
.child(
|
.child(
|
||||||
right_click_menu("test1")
|
right_click_menu("test1")
|
||||||
.trigger(Label::new("BOTTOM LEFT"))
|
.trigger(Label::new("BOTTOM LEFT"))
|
||||||
.anchor(AnchorCorner::BottomLeft)
|
.anchor(Corner::BottomLeft)
|
||||||
.attach(AnchorCorner::TopLeft)
|
.attach(Corner::TopLeft)
|
||||||
.menu(move |cx| build_menu(cx, "bottom left")),
|
.menu(move |cx| build_menu(cx, "bottom left")),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -60,14 +60,14 @@ impl Render for ContextMenuStory {
|
||||||
.child(
|
.child(
|
||||||
right_click_menu("test3")
|
right_click_menu("test3")
|
||||||
.trigger(Label::new("TOP RIGHT"))
|
.trigger(Label::new("TOP RIGHT"))
|
||||||
.anchor(AnchorCorner::TopRight)
|
.anchor(Corner::TopRight)
|
||||||
.menu(move |cx| build_menu(cx, "top right")),
|
.menu(move |cx| build_menu(cx, "top right")),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
right_click_menu("test4")
|
right_click_menu("test4")
|
||||||
.trigger(Label::new("BOTTOM RIGHT"))
|
.trigger(Label::new("BOTTOM RIGHT"))
|
||||||
.anchor(AnchorCorner::BottomRight)
|
.anchor(Corner::BottomRight)
|
||||||
.attach(AnchorCorner::TopRight)
|
.attach(Corner::TopRight)
|
||||||
.menu(move |cx| build_menu(cx, "bottom right")),
|
.menu(move |cx| build_menu(cx, "bottom right")),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,10 +3,10 @@ use crate::{status_bar::StatusItemView, Workspace};
|
||||||
use crate::{DraggedDock, Event, Pane};
|
use crate::{DraggedDock, Event, Pane};
|
||||||
use client::proto;
|
use client::proto;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
deferred, div, px, Action, AnchorCorner, AnyView, AppContext, Axis, Entity, EntityId,
|
deferred, div, px, Action, AnyView, AppContext, Axis, Corner, Entity, EntityId, EventEmitter,
|
||||||
EventEmitter, FocusHandle, FocusableView, IntoElement, KeyContext, MouseButton, MouseDownEvent,
|
FocusHandle, FocusableView, IntoElement, KeyContext, MouseButton, MouseDownEvent, MouseUpEvent,
|
||||||
MouseUpEvent, ParentElement, Render, SharedString, StyleRefinement, Styled, Subscription, View,
|
ParentElement, Render, SharedString, StyleRefinement, Styled, Subscription, View, ViewContext,
|
||||||
ViewContext, VisualContext, WeakView, WindowContext,
|
VisualContext, WeakView, WindowContext,
|
||||||
};
|
};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -719,10 +719,8 @@ impl Render for PanelButtons {
|
||||||
let dock_position = dock.position;
|
let dock_position = dock.position;
|
||||||
|
|
||||||
let (menu_anchor, menu_attach) = match dock.position {
|
let (menu_anchor, menu_attach) = match dock.position {
|
||||||
DockPosition::Left => (AnchorCorner::BottomLeft, AnchorCorner::TopLeft),
|
DockPosition::Left => (Corner::BottomLeft, Corner::TopLeft),
|
||||||
DockPosition::Bottom | DockPosition::Right => {
|
DockPosition::Bottom | DockPosition::Right => (Corner::BottomRight, Corner::TopRight),
|
||||||
(AnchorCorner::BottomRight, AnchorCorner::TopRight)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let buttons = dock
|
let buttons = dock
|
||||||
|
|
|
@ -14,8 +14,8 @@ use anyhow::Result;
|
||||||
use collections::{BTreeSet, HashMap, HashSet, VecDeque};
|
use collections::{BTreeSet, HashMap, HashSet, VecDeque};
|
||||||
use futures::{stream::FuturesUnordered, StreamExt};
|
use futures::{stream::FuturesUnordered, StreamExt};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, anchored, deferred, impl_actions, prelude::*, Action, AnchorCorner, AnyElement,
|
actions, anchored, deferred, impl_actions, prelude::*, Action, AnyElement, AppContext,
|
||||||
AppContext, AsyncWindowContext, ClickEvent, ClipboardItem, Div, DragMoveEvent, EntityId,
|
AsyncWindowContext, ClickEvent, ClipboardItem, Corner, Div, DragMoveEvent, EntityId,
|
||||||
EventEmitter, ExternalPaths, FocusHandle, FocusOutEvent, FocusableView, KeyContext, Model,
|
EventEmitter, ExternalPaths, FocusHandle, FocusOutEvent, FocusableView, KeyContext, Model,
|
||||||
MouseButton, MouseDownEvent, NavigationDirection, Pixels, Point, PromptLevel, Render,
|
MouseButton, MouseDownEvent, NavigationDirection, Pixels, Point, PromptLevel, Render,
|
||||||
ScrollHandle, Subscription, Task, View, ViewContext, VisualContext, WeakFocusHandle, WeakView,
|
ScrollHandle, Subscription, Task, View, ViewContext, VisualContext, WeakFocusHandle, WeakView,
|
||||||
|
@ -432,7 +432,7 @@ impl Pane {
|
||||||
.icon_size(IconSize::Small)
|
.icon_size(IconSize::Small)
|
||||||
.tooltip(|cx| Tooltip::text("New...", cx)),
|
.tooltip(|cx| Tooltip::text("New...", cx)),
|
||||||
)
|
)
|
||||||
.anchor(AnchorCorner::TopRight)
|
.anchor(Corner::TopRight)
|
||||||
.with_handle(pane.new_item_context_menu_handle.clone())
|
.with_handle(pane.new_item_context_menu_handle.clone())
|
||||||
.menu(move |cx| {
|
.menu(move |cx| {
|
||||||
Some(ContextMenu::build(cx, |menu, _| {
|
Some(ContextMenu::build(cx, |menu, _| {
|
||||||
|
@ -465,7 +465,7 @@ impl Pane {
|
||||||
.icon_size(IconSize::Small)
|
.icon_size(IconSize::Small)
|
||||||
.tooltip(|cx| Tooltip::text("Split Pane", cx)),
|
.tooltip(|cx| Tooltip::text("Split Pane", cx)),
|
||||||
)
|
)
|
||||||
.anchor(AnchorCorner::TopRight)
|
.anchor(Corner::TopRight)
|
||||||
.with_handle(pane.split_item_context_menu_handle.clone())
|
.with_handle(pane.split_item_context_menu_handle.clone())
|
||||||
.menu(move |cx| {
|
.menu(move |cx| {
|
||||||
ContextMenu::build(cx, |menu, _| {
|
ContextMenu::build(cx, |menu, _| {
|
||||||
|
@ -2506,12 +2506,7 @@ impl Pane {
|
||||||
|
|
||||||
pub fn render_menu_overlay(menu: &View<ContextMenu>) -> Div {
|
pub fn render_menu_overlay(menu: &View<ContextMenu>) -> Div {
|
||||||
div().absolute().bottom_0().right_0().size_0().child(
|
div().absolute().bottom_0().right_0().size_0().child(
|
||||||
deferred(
|
deferred(anchored().anchor(Corner::TopRight).child(menu.clone())).with_priority(1),
|
||||||
anchored()
|
|
||||||
.anchor(AnchorCorner::TopRight)
|
|
||||||
.child(menu.clone()),
|
|
||||||
)
|
|
||||||
.with_priority(1),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -758,9 +758,9 @@ impl SplitDirection {
|
||||||
pub fn edge(&self, rect: Bounds<Pixels>) -> Pixels {
|
pub fn edge(&self, rect: Bounds<Pixels>) -> Pixels {
|
||||||
match self {
|
match self {
|
||||||
Self::Up => rect.origin.y,
|
Self::Up => rect.origin.y,
|
||||||
Self::Down => rect.lower_left().y,
|
Self::Down => rect.bottom_left().y,
|
||||||
Self::Left => rect.lower_left().x,
|
Self::Left => rect.bottom_left().x,
|
||||||
Self::Right => rect.lower_right().x,
|
Self::Right => rect.bottom_right().x,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -771,7 +771,7 @@ impl SplitDirection {
|
||||||
size: size(bounds.size.width, length),
|
size: size(bounds.size.width, length),
|
||||||
},
|
},
|
||||||
Self::Down => Bounds {
|
Self::Down => Bounds {
|
||||||
origin: point(bounds.lower_left().x, bounds.lower_left().y - length),
|
origin: point(bounds.bottom_left().x, bounds.bottom_left().y - length),
|
||||||
size: size(bounds.size.width, length),
|
size: size(bounds.size.width, length),
|
||||||
},
|
},
|
||||||
Self::Left => Bounds {
|
Self::Left => Bounds {
|
||||||
|
@ -779,7 +779,7 @@ impl SplitDirection {
|
||||||
size: size(length, bounds.size.height),
|
size: size(length, bounds.size.height),
|
||||||
},
|
},
|
||||||
Self::Right => Bounds {
|
Self::Right => Bounds {
|
||||||
origin: point(bounds.lower_right().x - length, bounds.lower_left().y),
|
origin: point(bounds.bottom_right().x - length, bounds.bottom_left().y),
|
||||||
size: size(length, bounds.size.height),
|
size: size(length, bounds.size.height),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ use editor::actions::{
|
||||||
};
|
};
|
||||||
use editor::{Editor, EditorSettings};
|
use editor::{Editor, EditorSettings};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
Action, AnchorCorner, ClickEvent, ElementId, EventEmitter, FocusHandle, FocusableView,
|
Action, ClickEvent, Corner, ElementId, EventEmitter, FocusHandle, FocusableView,
|
||||||
InteractiveElement, ParentElement, Render, Styled, Subscription, View, ViewContext, WeakView,
|
InteractiveElement, ParentElement, Render, Styled, Subscription, View, ViewContext, WeakView,
|
||||||
};
|
};
|
||||||
use search::{buffer_search, BufferSearchBar};
|
use search::{buffer_search, BufferSearchBar};
|
||||||
|
@ -168,7 +168,7 @@ impl Render for QuickActionBar {
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.with_handle(self.toggle_selections_handle.clone())
|
.with_handle(self.toggle_selections_handle.clone())
|
||||||
.anchor(AnchorCorner::TopRight)
|
.anchor(Corner::TopRight)
|
||||||
.menu(move |cx| {
|
.menu(move |cx| {
|
||||||
let focus = focus.clone();
|
let focus = focus.clone();
|
||||||
let menu = ContextMenu::build(cx, move |menu, _| {
|
let menu = ContextMenu::build(cx, move |menu, _| {
|
||||||
|
@ -217,7 +217,7 @@ impl Render for QuickActionBar {
|
||||||
this.tooltip(|cx| Tooltip::text("Editor Controls", cx))
|
this.tooltip(|cx| Tooltip::text("Editor Controls", cx))
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.anchor(AnchorCorner::TopRight)
|
.anchor(Corner::TopRight)
|
||||||
.with_handle(self.toggle_settings_handle.clone())
|
.with_handle(self.toggle_settings_handle.clone())
|
||||||
.menu(move |cx| {
|
.menu(move |cx| {
|
||||||
let menu = ContextMenu::build(cx, |mut menu, _| {
|
let menu = ContextMenu::build(cx, |mut menu, _| {
|
||||||
|
|
Loading…
Reference in a new issue