Merge pull request #75 from zed-industries/naming-cleanup
Clean up naming conventions project-wide
This commit is contained in:
+10
-10
@@ -10,9 +10,9 @@ use simplelog::SimpleLogger;
|
||||
fn main() {
|
||||
SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
|
||||
|
||||
gpui::App::new(()).unwrap().run(|ctx| {
|
||||
ctx.platform().activate(true);
|
||||
ctx.add_window(|_| TextView);
|
||||
gpui::App::new(()).unwrap().run(|cx| {
|
||||
cx.platform().activate(true);
|
||||
cx.add_window(|_| TextView);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -58,15 +58,15 @@ impl gpui::Element for TextElement {
|
||||
&mut self,
|
||||
bounds: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut gpui::PaintContext,
|
||||
cx: &mut gpui::PaintContext,
|
||||
) -> Self::PaintState {
|
||||
let font_size = 12.;
|
||||
let family = ctx.font_cache.load_family(&["SF Pro Display"]).unwrap();
|
||||
let normal = ctx
|
||||
let family = cx.font_cache.load_family(&["SF Pro Display"]).unwrap();
|
||||
let normal = cx
|
||||
.font_cache
|
||||
.select_font(family, &Default::default())
|
||||
.unwrap();
|
||||
let bold = ctx
|
||||
let bold = cx
|
||||
.font_cache
|
||||
.select_font(
|
||||
family,
|
||||
@@ -78,7 +78,7 @@ impl gpui::Element for TextElement {
|
||||
.unwrap();
|
||||
|
||||
let text = "Hello world!";
|
||||
let line = ctx.text_layout_cache.layout_str(
|
||||
let line = cx.text_layout_cache.layout_str(
|
||||
text,
|
||||
font_size,
|
||||
&[
|
||||
@@ -90,12 +90,12 @@ impl gpui::Element for TextElement {
|
||||
],
|
||||
);
|
||||
|
||||
ctx.scene.push_quad(Quad {
|
||||
cx.scene.push_quad(Quad {
|
||||
bounds: bounds,
|
||||
background: Some(ColorU::white()),
|
||||
..Default::default()
|
||||
});
|
||||
line.paint(bounds.origin(), bounds, ctx);
|
||||
line.paint(bounds.origin(), bounds, cx);
|
||||
}
|
||||
|
||||
fn dispatch_event(
|
||||
|
||||
+381
-465
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,36 @@
|
||||
mod align;
|
||||
mod canvas;
|
||||
mod constrained_box;
|
||||
mod container;
|
||||
mod empty;
|
||||
mod event_handler;
|
||||
mod flex;
|
||||
mod label;
|
||||
mod line_box;
|
||||
mod mouse_event_handler;
|
||||
mod stack;
|
||||
mod svg;
|
||||
mod uniform_list;
|
||||
|
||||
pub use crate::presenter::ChildView;
|
||||
pub use align::*;
|
||||
pub use canvas::*;
|
||||
pub use constrained_box::*;
|
||||
pub use container::*;
|
||||
pub use empty::*;
|
||||
pub use event_handler::*;
|
||||
pub use flex::*;
|
||||
pub use label::*;
|
||||
pub use line_box::*;
|
||||
pub use mouse_event_handler::*;
|
||||
pub use stack::*;
|
||||
pub use svg::*;
|
||||
pub use uniform_list::*;
|
||||
|
||||
use crate::{
|
||||
geometry::{rect::RectF, vector::Vector2F},
|
||||
json, AfterLayoutContext, DebugContext, Event, EventContext, LayoutContext, PaintContext,
|
||||
SizeConstraint,
|
||||
json, AfterLayoutContext, AppContext, DebugContext, Event, EventContext, LayoutContext,
|
||||
PaintContext, SizeConstraint,
|
||||
};
|
||||
use core::panic;
|
||||
use json::ToJson;
|
||||
@@ -9,11 +38,11 @@ use replace_with::replace_with_or_abort;
|
||||
use std::{any::Any, borrow::Cow};
|
||||
|
||||
trait AnyElement {
|
||||
fn layout(&mut self, constraint: SizeConstraint, ctx: &mut LayoutContext) -> Vector2F;
|
||||
fn layout(&mut self, constraint: SizeConstraint, cx: &mut LayoutContext) -> Vector2F;
|
||||
fn after_layout(&mut self, _: &mut AfterLayoutContext) {}
|
||||
fn paint(&mut self, origin: Vector2F, ctx: &mut PaintContext);
|
||||
fn dispatch_event(&mut self, event: &Event, ctx: &mut EventContext) -> bool;
|
||||
fn debug(&self, ctx: &DebugContext) -> serde_json::Value;
|
||||
fn paint(&mut self, origin: Vector2F, cx: &mut PaintContext);
|
||||
fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool;
|
||||
fn debug(&self, cx: &DebugContext) -> serde_json::Value;
|
||||
|
||||
fn size(&self) -> Vector2F;
|
||||
fn metadata(&self) -> Option<&dyn Any>;
|
||||
@@ -26,21 +55,21 @@ pub trait Element {
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
ctx: &mut LayoutContext,
|
||||
cx: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState);
|
||||
|
||||
fn after_layout(
|
||||
&mut self,
|
||||
size: Vector2F,
|
||||
layout: &mut Self::LayoutState,
|
||||
ctx: &mut AfterLayoutContext,
|
||||
cx: &mut AfterLayoutContext,
|
||||
);
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: RectF,
|
||||
layout: &mut Self::LayoutState,
|
||||
ctx: &mut PaintContext,
|
||||
cx: &mut PaintContext,
|
||||
) -> Self::PaintState;
|
||||
|
||||
fn dispatch_event(
|
||||
@@ -49,7 +78,7 @@ pub trait Element {
|
||||
bounds: RectF,
|
||||
layout: &mut Self::LayoutState,
|
||||
paint: &mut Self::PaintState,
|
||||
ctx: &mut EventContext,
|
||||
cx: &mut EventContext,
|
||||
) -> bool;
|
||||
|
||||
fn metadata(&self) -> Option<&dyn Any> {
|
||||
@@ -61,7 +90,7 @@ pub trait Element {
|
||||
bounds: RectF,
|
||||
layout: &Self::LayoutState,
|
||||
paint: &Self::PaintState,
|
||||
ctx: &DebugContext,
|
||||
cx: &DebugContext,
|
||||
) -> serde_json::Value;
|
||||
|
||||
fn boxed(self) -> ElementBox
|
||||
@@ -109,13 +138,13 @@ pub struct ElementBox {
|
||||
}
|
||||
|
||||
impl<T: Element> AnyElement for Lifecycle<T> {
|
||||
fn layout(&mut self, constraint: SizeConstraint, ctx: &mut LayoutContext) -> Vector2F {
|
||||
fn layout(&mut self, constraint: SizeConstraint, cx: &mut LayoutContext) -> Vector2F {
|
||||
let mut result = None;
|
||||
replace_with_or_abort(self, |me| match me {
|
||||
Lifecycle::Init { mut element }
|
||||
| Lifecycle::PostLayout { mut element, .. }
|
||||
| Lifecycle::PostPaint { mut element, .. } => {
|
||||
let (size, layout) = element.layout(constraint, ctx);
|
||||
let (size, layout) = element.layout(constraint, cx);
|
||||
debug_assert!(size.x().is_finite());
|
||||
debug_assert!(size.y().is_finite());
|
||||
|
||||
@@ -131,7 +160,7 @@ impl<T: Element> AnyElement for Lifecycle<T> {
|
||||
result.unwrap()
|
||||
}
|
||||
|
||||
fn after_layout(&mut self, ctx: &mut AfterLayoutContext) {
|
||||
fn after_layout(&mut self, cx: &mut AfterLayoutContext) {
|
||||
if let Lifecycle::PostLayout {
|
||||
element,
|
||||
size,
|
||||
@@ -139,13 +168,13 @@ impl<T: Element> AnyElement for Lifecycle<T> {
|
||||
..
|
||||
} = self
|
||||
{
|
||||
element.after_layout(*size, layout, ctx);
|
||||
element.after_layout(*size, layout, cx);
|
||||
} else {
|
||||
panic!("invalid element lifecycle state");
|
||||
}
|
||||
}
|
||||
|
||||
fn paint(&mut self, origin: Vector2F, ctx: &mut PaintContext) {
|
||||
fn paint(&mut self, origin: Vector2F, cx: &mut PaintContext) {
|
||||
replace_with_or_abort(self, |me| {
|
||||
if let Lifecycle::PostLayout {
|
||||
mut element,
|
||||
@@ -155,7 +184,7 @@ impl<T: Element> AnyElement for Lifecycle<T> {
|
||||
} = me
|
||||
{
|
||||
let bounds = RectF::new(origin, size);
|
||||
let paint = element.paint(bounds, &mut layout, ctx);
|
||||
let paint = element.paint(bounds, &mut layout, cx);
|
||||
Lifecycle::PostPaint {
|
||||
element,
|
||||
constraint,
|
||||
@@ -169,7 +198,7 @@ impl<T: Element> AnyElement for Lifecycle<T> {
|
||||
});
|
||||
}
|
||||
|
||||
fn dispatch_event(&mut self, event: &Event, ctx: &mut EventContext) -> bool {
|
||||
fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool {
|
||||
if let Lifecycle::PostPaint {
|
||||
element,
|
||||
bounds,
|
||||
@@ -178,7 +207,7 @@ impl<T: Element> AnyElement for Lifecycle<T> {
|
||||
..
|
||||
} = self
|
||||
{
|
||||
element.dispatch_event(event, *bounds, layout, paint, ctx)
|
||||
element.dispatch_event(event, *bounds, layout, paint, cx)
|
||||
} else {
|
||||
panic!("invalid element lifecycle state");
|
||||
}
|
||||
@@ -200,7 +229,7 @@ impl<T: Element> AnyElement for Lifecycle<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn debug(&self, ctx: &DebugContext) -> serde_json::Value {
|
||||
fn debug(&self, cx: &DebugContext) -> serde_json::Value {
|
||||
match self {
|
||||
Lifecycle::PostPaint {
|
||||
element,
|
||||
@@ -209,7 +238,7 @@ impl<T: Element> AnyElement for Lifecycle<T> {
|
||||
layout,
|
||||
paint,
|
||||
} => {
|
||||
let mut value = element.debug(*bounds, layout, paint, ctx);
|
||||
let mut value = element.debug(*bounds, layout, paint, cx);
|
||||
if let json::Value::Object(map) = &mut value {
|
||||
let mut new_map: crate::json::Map<String, serde_json::Value> =
|
||||
Default::default();
|
||||
@@ -229,20 +258,20 @@ impl<T: Element> AnyElement for Lifecycle<T> {
|
||||
}
|
||||
|
||||
impl ElementBox {
|
||||
pub fn layout(&mut self, constraint: SizeConstraint, ctx: &mut LayoutContext) -> Vector2F {
|
||||
self.element.layout(constraint, ctx)
|
||||
pub fn layout(&mut self, constraint: SizeConstraint, cx: &mut LayoutContext) -> Vector2F {
|
||||
self.element.layout(constraint, cx)
|
||||
}
|
||||
|
||||
pub fn after_layout(&mut self, ctx: &mut AfterLayoutContext) {
|
||||
self.element.after_layout(ctx);
|
||||
pub fn after_layout(&mut self, cx: &mut AfterLayoutContext) {
|
||||
self.element.after_layout(cx);
|
||||
}
|
||||
|
||||
pub fn paint(&mut self, origin: Vector2F, ctx: &mut PaintContext) {
|
||||
self.element.paint(origin, ctx);
|
||||
pub fn paint(&mut self, origin: Vector2F, cx: &mut PaintContext) {
|
||||
self.element.paint(origin, cx);
|
||||
}
|
||||
|
||||
pub fn dispatch_event(&mut self, event: &Event, ctx: &mut EventContext) -> bool {
|
||||
self.element.dispatch_event(event, ctx)
|
||||
pub fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool {
|
||||
self.element.dispatch_event(event, cx)
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Vector2F {
|
||||
@@ -253,8 +282,8 @@ impl ElementBox {
|
||||
self.element.metadata()
|
||||
}
|
||||
|
||||
pub fn debug(&self, ctx: &DebugContext) -> json::Value {
|
||||
let mut value = self.element.debug(ctx);
|
||||
pub fn debug(&self, cx: &DebugContext) -> json::Value {
|
||||
let mut value = self.element.debug(cx);
|
||||
|
||||
if let Some(name) = &self.name {
|
||||
if let json::Value::Object(map) = &mut value {
|
||||
@@ -268,3 +297,24 @@ impl ElementBox {
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ParentElement<'a>: Extend<ElementBox> + Sized {
|
||||
fn add_children(&mut self, children: impl IntoIterator<Item = ElementBox>) {
|
||||
self.extend(children);
|
||||
}
|
||||
|
||||
fn add_child(&mut self, child: ElementBox) {
|
||||
self.add_children(Some(child));
|
||||
}
|
||||
|
||||
fn with_children(mut self, children: impl IntoIterator<Item = ElementBox>) -> Self {
|
||||
self.add_children(children);
|
||||
self
|
||||
}
|
||||
|
||||
fn with_child(self, child: ElementBox) -> Self {
|
||||
self.with_children(Some(child))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> ParentElement<'a> for T where T: Extend<ElementBox> {}
|
||||
+10
-10
@@ -37,11 +37,11 @@ impl Element for Align {
|
||||
fn layout(
|
||||
&mut self,
|
||||
mut constraint: SizeConstraint,
|
||||
ctx: &mut LayoutContext,
|
||||
cx: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let mut size = constraint.max;
|
||||
constraint.min = Vector2F::zero();
|
||||
let child_size = self.child.layout(constraint, ctx);
|
||||
let child_size = self.child.layout(constraint, cx);
|
||||
if size.x().is_infinite() {
|
||||
size.set_x(child_size.x());
|
||||
}
|
||||
@@ -55,16 +55,16 @@ impl Element for Align {
|
||||
&mut self,
|
||||
_: Vector2F,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut AfterLayoutContext,
|
||||
cx: &mut AfterLayoutContext,
|
||||
) {
|
||||
self.child.after_layout(ctx);
|
||||
self.child.after_layout(cx);
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: pathfinder_geometry::rect::RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut PaintContext,
|
||||
cx: &mut PaintContext,
|
||||
) -> Self::PaintState {
|
||||
let my_center = bounds.size() / 2.;
|
||||
let my_target = my_center + my_center * self.alignment;
|
||||
@@ -73,7 +73,7 @@ impl Element for Align {
|
||||
let child_target = child_center + child_center * self.alignment;
|
||||
|
||||
self.child
|
||||
.paint(bounds.origin() - (child_target - my_target), ctx);
|
||||
.paint(bounds.origin() - (child_target - my_target), cx);
|
||||
}
|
||||
|
||||
fn dispatch_event(
|
||||
@@ -82,9 +82,9 @@ impl Element for Align {
|
||||
_: pathfinder_geometry::rect::RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
_: &mut Self::PaintState,
|
||||
ctx: &mut EventContext,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
self.child.dispatch_event(event, ctx)
|
||||
self.child.dispatch_event(event, cx)
|
||||
}
|
||||
|
||||
fn debug(
|
||||
@@ -92,13 +92,13 @@ impl Element for Align {
|
||||
bounds: pathfinder_geometry::rect::RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
ctx: &DebugContext,
|
||||
cx: &DebugContext,
|
||||
) -> json::Value {
|
||||
json!({
|
||||
"type": "Align",
|
||||
"bounds": bounds.to_json(),
|
||||
"alignment": self.alignment.to_json(),
|
||||
"child": self.child.debug(ctx),
|
||||
"child": self.child.debug(cx),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,9 +51,9 @@ where
|
||||
&mut self,
|
||||
bounds: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut PaintContext,
|
||||
cx: &mut PaintContext,
|
||||
) -> Self::PaintState {
|
||||
self.0(bounds, ctx)
|
||||
self.0(bounds, cx)
|
||||
}
|
||||
|
||||
fn after_layout(
|
||||
|
||||
@@ -58,12 +58,12 @@ impl Element for ConstrainedBox {
|
||||
fn layout(
|
||||
&mut self,
|
||||
mut constraint: SizeConstraint,
|
||||
ctx: &mut LayoutContext,
|
||||
cx: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
constraint.min = constraint.min.max(self.constraint.min);
|
||||
constraint.max = constraint.max.min(self.constraint.max);
|
||||
constraint.max = constraint.max.max(constraint.min);
|
||||
let size = self.child.layout(constraint, ctx);
|
||||
let size = self.child.layout(constraint, cx);
|
||||
(size, ())
|
||||
}
|
||||
|
||||
@@ -71,18 +71,18 @@ impl Element for ConstrainedBox {
|
||||
&mut self,
|
||||
_: Vector2F,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut AfterLayoutContext,
|
||||
cx: &mut AfterLayoutContext,
|
||||
) {
|
||||
self.child.after_layout(ctx);
|
||||
self.child.after_layout(cx);
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut PaintContext,
|
||||
cx: &mut PaintContext,
|
||||
) -> Self::PaintState {
|
||||
self.child.paint(bounds.origin(), ctx);
|
||||
self.child.paint(bounds.origin(), cx);
|
||||
}
|
||||
|
||||
fn dispatch_event(
|
||||
@@ -91,9 +91,9 @@ impl Element for ConstrainedBox {
|
||||
_: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
_: &mut Self::PaintState,
|
||||
ctx: &mut EventContext,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
self.child.dispatch_event(event, ctx)
|
||||
self.child.dispatch_event(event, cx)
|
||||
}
|
||||
|
||||
fn debug(
|
||||
@@ -101,8 +101,8 @@ impl Element for ConstrainedBox {
|
||||
_: RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
ctx: &DebugContext,
|
||||
cx: &DebugContext,
|
||||
) -> json::Value {
|
||||
json!({"type": "ConstrainedBox", "set_constraint": self.constraint.to_json(), "child": self.child.debug(ctx)})
|
||||
json!({"type": "ConstrainedBox", "set_constraint": self.constraint.to_json(), "child": self.child.debug(cx)})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,14 +141,14 @@ impl Element for Container {
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
ctx: &mut LayoutContext,
|
||||
cx: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let size_buffer = self.margin_size() + self.padding_size() + self.border_size();
|
||||
let child_constraint = SizeConstraint {
|
||||
min: (constraint.min - size_buffer).max(Vector2F::zero()),
|
||||
max: (constraint.max - size_buffer).max(Vector2F::zero()),
|
||||
};
|
||||
let child_size = self.child.layout(child_constraint, ctx);
|
||||
let child_size = self.child.layout(child_constraint, cx);
|
||||
(child_size + size_buffer, ())
|
||||
}
|
||||
|
||||
@@ -156,16 +156,16 @@ impl Element for Container {
|
||||
&mut self,
|
||||
_: Vector2F,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut AfterLayoutContext,
|
||||
cx: &mut AfterLayoutContext,
|
||||
) {
|
||||
self.child.after_layout(ctx);
|
||||
self.child.after_layout(cx);
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut PaintContext,
|
||||
cx: &mut PaintContext,
|
||||
) -> Self::PaintState {
|
||||
let quad_bounds = RectF::from_points(
|
||||
bounds.origin() + vec2f(self.margin.left, self.margin.top),
|
||||
@@ -173,14 +173,14 @@ impl Element for Container {
|
||||
);
|
||||
|
||||
if let Some(shadow) = self.shadow.as_ref() {
|
||||
ctx.scene.push_shadow(scene::Shadow {
|
||||
cx.scene.push_shadow(scene::Shadow {
|
||||
bounds: quad_bounds + shadow.offset,
|
||||
corner_radius: self.corner_radius,
|
||||
sigma: shadow.blur,
|
||||
color: shadow.color,
|
||||
});
|
||||
}
|
||||
ctx.scene.push_quad(Quad {
|
||||
cx.scene.push_quad(Quad {
|
||||
bounds: quad_bounds,
|
||||
background: self.background_color,
|
||||
border: self.border,
|
||||
@@ -190,7 +190,7 @@ impl Element for Container {
|
||||
let child_origin = quad_bounds.origin()
|
||||
+ vec2f(self.padding.left, self.padding.top)
|
||||
+ vec2f(self.border.left_width(), self.border.top_width());
|
||||
self.child.paint(child_origin, ctx);
|
||||
self.child.paint(child_origin, cx);
|
||||
}
|
||||
|
||||
fn dispatch_event(
|
||||
@@ -199,9 +199,9 @@ impl Element for Container {
|
||||
_: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
_: &mut Self::PaintState,
|
||||
ctx: &mut EventContext,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
self.child.dispatch_event(event, ctx)
|
||||
self.child.dispatch_event(event, cx)
|
||||
}
|
||||
|
||||
fn debug(
|
||||
@@ -209,7 +209,7 @@ impl Element for Container {
|
||||
bounds: RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
ctx: &crate::DebugContext,
|
||||
cx: &crate::DebugContext,
|
||||
) -> serde_json::Value {
|
||||
json!({
|
||||
"type": "Container",
|
||||
@@ -222,7 +222,7 @@ impl Element for Container {
|
||||
"corner_radius": self.corner_radius,
|
||||
"shadow": self.shadow.to_json(),
|
||||
},
|
||||
"child": self.child.debug(ctx),
|
||||
"child": self.child.debug(cx),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,9 +35,9 @@ impl Element for EventHandler {
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
ctx: &mut LayoutContext,
|
||||
cx: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let size = self.child.layout(constraint, ctx);
|
||||
let size = self.child.layout(constraint, cx);
|
||||
(size, ())
|
||||
}
|
||||
|
||||
@@ -45,18 +45,18 @@ impl Element for EventHandler {
|
||||
&mut self,
|
||||
_: Vector2F,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut AfterLayoutContext,
|
||||
cx: &mut AfterLayoutContext,
|
||||
) {
|
||||
self.child.after_layout(ctx);
|
||||
self.child.after_layout(cx);
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut PaintContext,
|
||||
cx: &mut PaintContext,
|
||||
) -> Self::PaintState {
|
||||
self.child.paint(bounds.origin(), ctx);
|
||||
self.child.paint(bounds.origin(), cx);
|
||||
}
|
||||
|
||||
fn dispatch_event(
|
||||
@@ -65,16 +65,16 @@ impl Element for EventHandler {
|
||||
bounds: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
_: &mut Self::PaintState,
|
||||
ctx: &mut EventContext,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
if self.child.dispatch_event(event, ctx) {
|
||||
if self.child.dispatch_event(event, cx) {
|
||||
true
|
||||
} else {
|
||||
match event {
|
||||
Event::LeftMouseDown { position, .. } => {
|
||||
if let Some(callback) = self.mouse_down.as_mut() {
|
||||
if bounds.contains_point(*position) {
|
||||
return callback(ctx);
|
||||
return callback(cx);
|
||||
}
|
||||
}
|
||||
false
|
||||
@@ -89,11 +89,11 @@ impl Element for EventHandler {
|
||||
_: RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
ctx: &DebugContext,
|
||||
cx: &DebugContext,
|
||||
) -> serde_json::Value {
|
||||
json!({
|
||||
"type": "EventHandler",
|
||||
"child": self.child.debug(ctx),
|
||||
"child": self.child.debug(cx),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+21
-21
@@ -53,7 +53,7 @@ impl Element for Flex {
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
ctx: &mut LayoutContext,
|
||||
cx: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let mut total_flex = 0.0;
|
||||
let mut fixed_space = 0.0;
|
||||
@@ -74,7 +74,7 @@ impl Element for Flex {
|
||||
vec2f(constraint.max.x(), INFINITY),
|
||||
),
|
||||
};
|
||||
let size = child.layout(child_constraint, ctx);
|
||||
let size = child.layout(child_constraint, cx);
|
||||
fixed_space += size.along(self.axis);
|
||||
cross_axis_max = cross_axis_max.max(size.along(cross_axis));
|
||||
}
|
||||
@@ -105,7 +105,7 @@ impl Element for Flex {
|
||||
vec2f(constraint.max.x(), child_max),
|
||||
),
|
||||
};
|
||||
let child_size = child.layout(child_constraint, ctx);
|
||||
let child_size = child.layout(child_constraint, cx);
|
||||
remaining_space -= child_size.along(self.axis);
|
||||
remaining_flex -= flex;
|
||||
cross_axis_max = cross_axis_max.max(child_size.along(cross_axis));
|
||||
@@ -138,10 +138,10 @@ impl Element for Flex {
|
||||
&mut self,
|
||||
_: Vector2F,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut AfterLayoutContext,
|
||||
cx: &mut AfterLayoutContext,
|
||||
) {
|
||||
for child in &mut self.children {
|
||||
child.after_layout(ctx);
|
||||
child.after_layout(cx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,11 +149,11 @@ impl Element for Flex {
|
||||
&mut self,
|
||||
bounds: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut PaintContext,
|
||||
cx: &mut PaintContext,
|
||||
) -> Self::PaintState {
|
||||
let mut child_origin = bounds.origin();
|
||||
for child in &mut self.children {
|
||||
child.paint(child_origin, ctx);
|
||||
child.paint(child_origin, cx);
|
||||
match self.axis {
|
||||
Axis::Horizontal => child_origin += vec2f(child.size().x(), 0.0),
|
||||
Axis::Vertical => child_origin += vec2f(0.0, child.size().y()),
|
||||
@@ -167,11 +167,11 @@ impl Element for Flex {
|
||||
_: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
_: &mut Self::PaintState,
|
||||
ctx: &mut EventContext,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
let mut handled = false;
|
||||
for child in &mut self.children {
|
||||
handled = child.dispatch_event(event, ctx) || handled;
|
||||
handled = child.dispatch_event(event, cx) || handled;
|
||||
}
|
||||
handled
|
||||
}
|
||||
@@ -181,13 +181,13 @@ impl Element for Flex {
|
||||
bounds: RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
ctx: &DebugContext,
|
||||
cx: &DebugContext,
|
||||
) -> json::Value {
|
||||
json!({
|
||||
"type": "Flex",
|
||||
"bounds": bounds.to_json(),
|
||||
"axis": self.axis.to_json(),
|
||||
"children": self.children.iter().map(|child| child.debug(ctx)).collect::<Vec<json::Value>>()
|
||||
"children": self.children.iter().map(|child| child.debug(cx)).collect::<Vec<json::Value>>()
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -217,9 +217,9 @@ impl Element for Expanded {
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
ctx: &mut LayoutContext,
|
||||
cx: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let size = self.child.layout(constraint, ctx);
|
||||
let size = self.child.layout(constraint, cx);
|
||||
(size, ())
|
||||
}
|
||||
|
||||
@@ -227,18 +227,18 @@ impl Element for Expanded {
|
||||
&mut self,
|
||||
_: Vector2F,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut AfterLayoutContext,
|
||||
cx: &mut AfterLayoutContext,
|
||||
) {
|
||||
self.child.after_layout(ctx);
|
||||
self.child.after_layout(cx);
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut PaintContext,
|
||||
cx: &mut PaintContext,
|
||||
) -> Self::PaintState {
|
||||
self.child.paint(bounds.origin(), ctx)
|
||||
self.child.paint(bounds.origin(), cx)
|
||||
}
|
||||
|
||||
fn dispatch_event(
|
||||
@@ -247,9 +247,9 @@ impl Element for Expanded {
|
||||
_: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
_: &mut Self::PaintState,
|
||||
ctx: &mut EventContext,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
self.child.dispatch_event(event, ctx)
|
||||
self.child.dispatch_event(event, cx)
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Option<&dyn Any> {
|
||||
@@ -261,12 +261,12 @@ impl Element for Expanded {
|
||||
_: RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
ctx: &DebugContext,
|
||||
cx: &DebugContext,
|
||||
) -> Value {
|
||||
json!({
|
||||
"type": "Expanded",
|
||||
"flex": self.metadata.flex,
|
||||
"child": self.child.debug(ctx)
|
||||
"child": self.child.debug(cx)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+14
-14
@@ -109,20 +109,20 @@ impl Element for Label {
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
ctx: &mut LayoutContext,
|
||||
cx: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let font_id = ctx
|
||||
let font_id = cx
|
||||
.font_cache
|
||||
.select_font(self.family_id, &self.font_properties)
|
||||
.unwrap();
|
||||
let runs = self.compute_runs(&ctx.font_cache, font_id);
|
||||
let runs = self.compute_runs(&cx.font_cache, font_id);
|
||||
let line =
|
||||
ctx.text_layout_cache
|
||||
cx.text_layout_cache
|
||||
.layout_str(self.text.as_str(), self.font_size, runs.as_slice());
|
||||
|
||||
let size = vec2f(
|
||||
line.width().max(constraint.min.x()).min(constraint.max.x()),
|
||||
ctx.font_cache.line_height(font_id, self.font_size).ceil(),
|
||||
cx.font_cache.line_height(font_id, self.font_size).ceil(),
|
||||
);
|
||||
|
||||
(size, line)
|
||||
@@ -135,12 +135,12 @@ impl Element for Label {
|
||||
&mut self,
|
||||
bounds: RectF,
|
||||
line: &mut Self::LayoutState,
|
||||
ctx: &mut PaintContext,
|
||||
cx: &mut PaintContext,
|
||||
) -> Self::PaintState {
|
||||
line.paint(
|
||||
bounds.origin(),
|
||||
RectF::new(vec2f(0., 0.), bounds.size()),
|
||||
ctx,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -160,12 +160,12 @@ impl Element for Label {
|
||||
bounds: RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
ctx: &DebugContext,
|
||||
cx: &DebugContext,
|
||||
) -> Value {
|
||||
json!({
|
||||
"type": "Label",
|
||||
"bounds": bounds.to_json(),
|
||||
"font_family": ctx.font_cache.family_name(self.family_id).unwrap(),
|
||||
"font_family": cx.font_cache.family_name(self.family_id).unwrap(),
|
||||
"font_size": self.font_size,
|
||||
"font_properties": self.font_properties.to_json(),
|
||||
"text": &self.text,
|
||||
@@ -191,13 +191,13 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
#[crate::test(self)]
|
||||
fn test_layout_label_with_highlights(app: &mut crate::MutableAppContext) {
|
||||
let menlo = app.font_cache().load_family(&["Menlo"]).unwrap();
|
||||
let menlo_regular = app
|
||||
fn test_layout_label_with_highlights(cx: &mut crate::MutableAppContext) {
|
||||
let menlo = cx.font_cache().load_family(&["Menlo"]).unwrap();
|
||||
let menlo_regular = cx
|
||||
.font_cache()
|
||||
.select_font(menlo, &Properties::new())
|
||||
.unwrap();
|
||||
let menlo_bold = app
|
||||
let menlo_bold = cx
|
||||
.font_cache()
|
||||
.select_font(menlo, Properties::new().weight(Weight::BOLD))
|
||||
.unwrap();
|
||||
@@ -216,7 +216,7 @@ mod tests {
|
||||
],
|
||||
);
|
||||
|
||||
let runs = label.compute_runs(app.font_cache().as_ref(), menlo_regular);
|
||||
let runs = label.compute_runs(cx.font_cache().as_ref(), menlo_regular);
|
||||
assert_eq!(
|
||||
runs.as_slice(),
|
||||
&[
|
||||
|
||||
@@ -35,20 +35,20 @@ impl Element for LineBox {
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
ctx: &mut LayoutContext,
|
||||
cx: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
match ctx
|
||||
match cx
|
||||
.font_cache
|
||||
.select_font(self.family_id, &self.font_properties)
|
||||
{
|
||||
Ok(font_id) => {
|
||||
let line_height = ctx.font_cache.line_height(font_id, self.font_size);
|
||||
let character_height = ctx.font_cache.ascent(font_id, self.font_size)
|
||||
+ ctx.font_cache.descent(font_id, self.font_size);
|
||||
let line_height = cx.font_cache.line_height(font_id, self.font_size);
|
||||
let character_height = cx.font_cache.ascent(font_id, self.font_size)
|
||||
+ cx.font_cache.descent(font_id, self.font_size);
|
||||
let child_max = vec2f(constraint.max.x(), character_height);
|
||||
let child_size = self.child.layout(
|
||||
SizeConstraint::new(constraint.min.min(child_max), child_max),
|
||||
ctx,
|
||||
cx,
|
||||
);
|
||||
let size = vec2f(child_size.x(), line_height);
|
||||
(size, (line_height - character_height) / 2.)
|
||||
@@ -64,19 +64,19 @@ impl Element for LineBox {
|
||||
&mut self,
|
||||
_: Vector2F,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut AfterLayoutContext,
|
||||
cx: &mut AfterLayoutContext,
|
||||
) {
|
||||
self.child.after_layout(ctx);
|
||||
self.child.after_layout(cx);
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: pathfinder_geometry::rect::RectF,
|
||||
padding_top: &mut f32,
|
||||
ctx: &mut PaintContext,
|
||||
cx: &mut PaintContext,
|
||||
) -> Self::PaintState {
|
||||
self.child
|
||||
.paint(bounds.origin() + vec2f(0., *padding_top), ctx);
|
||||
.paint(bounds.origin() + vec2f(0., *padding_top), cx);
|
||||
}
|
||||
|
||||
fn dispatch_event(
|
||||
@@ -85,9 +85,9 @@ impl Element for LineBox {
|
||||
_: pathfinder_geometry::rect::RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
_: &mut Self::PaintState,
|
||||
ctx: &mut EventContext,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
self.child.dispatch_event(event, ctx)
|
||||
self.child.dispatch_event(event, cx)
|
||||
}
|
||||
|
||||
fn debug(
|
||||
@@ -95,14 +95,14 @@ impl Element for LineBox {
|
||||
bounds: RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
ctx: &DebugContext,
|
||||
cx: &DebugContext,
|
||||
) -> serde_json::Value {
|
||||
json!({
|
||||
"bounds": bounds.to_json(),
|
||||
"font_family": ctx.font_cache.family_name(self.family_id).unwrap(),
|
||||
"font_family": cx.font_cache.family_name(self.family_id).unwrap(),
|
||||
"font_size": self.font_size,
|
||||
"font_properties": self.font_properties.to_json(),
|
||||
"child": self.child.debug(ctx),
|
||||
"child": self.child.debug(cx),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
mod align;
|
||||
mod canvas;
|
||||
mod constrained_box;
|
||||
mod container;
|
||||
mod empty;
|
||||
mod event_handler;
|
||||
mod flex;
|
||||
mod label;
|
||||
mod line_box;
|
||||
mod mouse_event_handler;
|
||||
mod new;
|
||||
mod stack;
|
||||
mod svg;
|
||||
mod uniform_list;
|
||||
|
||||
pub use crate::presenter::ChildView;
|
||||
pub use align::*;
|
||||
pub use canvas::*;
|
||||
pub use constrained_box::*;
|
||||
pub use container::*;
|
||||
pub use empty::*;
|
||||
pub use event_handler::*;
|
||||
pub use flex::*;
|
||||
pub use label::*;
|
||||
pub use line_box::*;
|
||||
pub use mouse_event_handler::*;
|
||||
pub use new::*;
|
||||
pub use stack::*;
|
||||
pub use svg::*;
|
||||
pub use uniform_list::*;
|
||||
|
||||
use crate::{
|
||||
AfterLayoutContext, AppContext, Event, EventContext, LayoutContext, PaintContext,
|
||||
SizeConstraint,
|
||||
};
|
||||
|
||||
pub trait ParentElement<'a>: Extend<ElementBox> + Sized {
|
||||
fn add_children(&mut self, children: impl IntoIterator<Item = ElementBox>) {
|
||||
self.extend(children);
|
||||
}
|
||||
|
||||
fn add_child(&mut self, child: ElementBox) {
|
||||
self.add_children(Some(child));
|
||||
}
|
||||
|
||||
fn with_children(mut self, children: impl IntoIterator<Item = ElementBox>) -> Self {
|
||||
self.add_children(children);
|
||||
self
|
||||
}
|
||||
|
||||
fn with_child(self, child: ElementBox) -> Self {
|
||||
self.with_children(Some(child))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> ParentElement<'a> for T where T: Extend<ElementBox> {}
|
||||
@@ -18,13 +18,13 @@ pub struct MouseState {
|
||||
}
|
||||
|
||||
impl MouseEventHandler {
|
||||
pub fn new<Tag, F>(id: usize, ctx: &AppContext, render_child: F) -> Self
|
||||
pub fn new<Tag, F>(id: usize, cx: &AppContext, render_child: F) -> Self
|
||||
where
|
||||
Tag: 'static,
|
||||
F: FnOnce(MouseState) -> ElementBox,
|
||||
{
|
||||
let state_handle = ctx.value::<Tag, _>(id);
|
||||
let state = state_handle.read(ctx, |state| *state);
|
||||
let state_handle = cx.value::<Tag, _>(id);
|
||||
let state = state_handle.read(cx, |state| *state);
|
||||
let child = render_child(state);
|
||||
Self {
|
||||
state: state_handle,
|
||||
@@ -46,27 +46,27 @@ impl Element for MouseEventHandler {
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
ctx: &mut LayoutContext,
|
||||
cx: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
(self.child.layout(constraint, ctx), ())
|
||||
(self.child.layout(constraint, cx), ())
|
||||
}
|
||||
|
||||
fn after_layout(
|
||||
&mut self,
|
||||
_: Vector2F,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut AfterLayoutContext,
|
||||
cx: &mut AfterLayoutContext,
|
||||
) {
|
||||
self.child.after_layout(ctx);
|
||||
self.child.after_layout(cx);
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut PaintContext,
|
||||
cx: &mut PaintContext,
|
||||
) -> Self::PaintState {
|
||||
self.child.paint(bounds.origin(), ctx);
|
||||
self.child.paint(bounds.origin(), cx);
|
||||
}
|
||||
|
||||
fn dispatch_event(
|
||||
@@ -75,18 +75,18 @@ impl Element for MouseEventHandler {
|
||||
bounds: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
_: &mut Self::PaintState,
|
||||
ctx: &mut EventContext,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
let click_handler = self.click_handler.as_mut();
|
||||
|
||||
let handled_in_child = self.child.dispatch_event(event, ctx);
|
||||
let handled_in_child = self.child.dispatch_event(event, cx);
|
||||
|
||||
self.state.update(ctx.app, |state| match event {
|
||||
self.state.update(cx.app, |state| match event {
|
||||
Event::MouseMoved { position } => {
|
||||
let mouse_in = bounds.contains_point(*position);
|
||||
if state.hovered != mouse_in {
|
||||
state.hovered = mouse_in;
|
||||
ctx.notify();
|
||||
cx.notify();
|
||||
true
|
||||
} else {
|
||||
handled_in_child
|
||||
@@ -95,7 +95,7 @@ impl Element for MouseEventHandler {
|
||||
Event::LeftMouseDown { position, .. } => {
|
||||
if !handled_in_child && bounds.contains_point(*position) {
|
||||
state.clicked = true;
|
||||
ctx.notify();
|
||||
cx.notify();
|
||||
true
|
||||
} else {
|
||||
handled_in_child
|
||||
@@ -104,10 +104,10 @@ impl Element for MouseEventHandler {
|
||||
Event::LeftMouseUp { position, .. } => {
|
||||
if !handled_in_child && state.clicked {
|
||||
state.clicked = false;
|
||||
ctx.notify();
|
||||
cx.notify();
|
||||
if let Some(handler) = click_handler {
|
||||
if bounds.contains_point(*position) {
|
||||
handler(ctx);
|
||||
handler(cx);
|
||||
}
|
||||
}
|
||||
true
|
||||
@@ -124,11 +124,11 @@ impl Element for MouseEventHandler {
|
||||
_: RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
ctx: &DebugContext,
|
||||
cx: &DebugContext,
|
||||
) -> serde_json::Value {
|
||||
json!({
|
||||
"type": "MouseEventHandler",
|
||||
"child": self.child.debug(ctx),
|
||||
"child": self.child.debug(cx),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+12
-12
@@ -24,11 +24,11 @@ impl Element for Stack {
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
ctx: &mut LayoutContext,
|
||||
cx: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let mut size = constraint.min;
|
||||
for child in &mut self.children {
|
||||
size = size.max(child.layout(constraint, ctx));
|
||||
size = size.max(child.layout(constraint, cx));
|
||||
}
|
||||
(size, ())
|
||||
}
|
||||
@@ -37,10 +37,10 @@ impl Element for Stack {
|
||||
&mut self,
|
||||
_: Vector2F,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut AfterLayoutContext,
|
||||
cx: &mut AfterLayoutContext,
|
||||
) {
|
||||
for child in &mut self.children {
|
||||
child.after_layout(ctx);
|
||||
child.after_layout(cx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,12 +48,12 @@ impl Element for Stack {
|
||||
&mut self,
|
||||
bounds: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut PaintContext,
|
||||
cx: &mut PaintContext,
|
||||
) -> Self::PaintState {
|
||||
for child in &mut self.children {
|
||||
ctx.scene.push_layer(None);
|
||||
child.paint(bounds.origin(), ctx);
|
||||
ctx.scene.pop_layer();
|
||||
cx.scene.push_layer(None);
|
||||
child.paint(bounds.origin(), cx);
|
||||
cx.scene.pop_layer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,10 +63,10 @@ impl Element for Stack {
|
||||
_: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
_: &mut Self::PaintState,
|
||||
ctx: &mut EventContext,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
for child in self.children.iter_mut().rev() {
|
||||
if child.dispatch_event(event, ctx) {
|
||||
if child.dispatch_event(event, cx) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -78,12 +78,12 @@ impl Element for Stack {
|
||||
bounds: RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
ctx: &DebugContext,
|
||||
cx: &DebugContext,
|
||||
) -> json::Value {
|
||||
json!({
|
||||
"type": "Stack",
|
||||
"bounds": bounds.to_json(),
|
||||
"children": self.children.iter().map(|child| child.debug(ctx)).collect::<Vec<json::Value>>()
|
||||
"children": self.children.iter().map(|child| child.debug(cx)).collect::<Vec<json::Value>>()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,9 +38,9 @@ impl Element for Svg {
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
ctx: &mut LayoutContext,
|
||||
cx: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
match ctx.asset_cache.svg(&self.path) {
|
||||
match cx.asset_cache.svg(&self.path) {
|
||||
Ok(tree) => {
|
||||
let size = if constraint.max.x().is_infinite() && constraint.max.y().is_infinite() {
|
||||
let rect = from_usvg_rect(tree.svg_node().view_box.rect);
|
||||
@@ -69,9 +69,9 @@ impl Element for Svg {
|
||||
fn after_layout(&mut self, _: Vector2F, _: &mut Self::LayoutState, _: &mut AfterLayoutContext) {
|
||||
}
|
||||
|
||||
fn paint(&mut self, bounds: RectF, svg: &mut Self::LayoutState, ctx: &mut PaintContext) {
|
||||
fn paint(&mut self, bounds: RectF, svg: &mut Self::LayoutState, cx: &mut PaintContext) {
|
||||
if let Some(svg) = svg.clone() {
|
||||
ctx.scene.push_icon(scene::Icon {
|
||||
cx.scene.push_icon(scene::Icon {
|
||||
bounds,
|
||||
svg,
|
||||
path: self.path.clone(),
|
||||
|
||||
@@ -72,7 +72,7 @@ where
|
||||
delta: Vector2F,
|
||||
precise: bool,
|
||||
scroll_max: f32,
|
||||
ctx: &mut EventContext,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
if !precise {
|
||||
todo!("still need to handle non-precise scroll events from a mouse wheel");
|
||||
@@ -80,7 +80,7 @@ where
|
||||
|
||||
let mut state = self.state.0.lock();
|
||||
state.scroll_top = (state.scroll_top - delta.y()).max(0.0).min(scroll_max);
|
||||
ctx.dispatch_action("uniform_list:scroll", state.scroll_top);
|
||||
cx.dispatch_action("uniform_list:scroll", state.scroll_top);
|
||||
|
||||
true
|
||||
}
|
||||
@@ -119,7 +119,7 @@ where
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
ctx: &mut LayoutContext,
|
||||
cx: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
if constraint.max.y().is_infinite() {
|
||||
unimplemented!(
|
||||
@@ -133,9 +133,9 @@ where
|
||||
let mut scroll_max = 0.;
|
||||
|
||||
let mut items = Vec::new();
|
||||
(self.append_items)(0..1, &mut items, ctx.app);
|
||||
(self.append_items)(0..1, &mut items, cx.app);
|
||||
if let Some(first_item) = items.first_mut() {
|
||||
let mut item_size = first_item.layout(item_constraint, ctx);
|
||||
let mut item_size = first_item.layout(item_constraint, cx);
|
||||
item_size.set_x(size.x());
|
||||
item_constraint.min = item_size;
|
||||
item_constraint.max = item_size;
|
||||
@@ -155,9 +155,9 @@ where
|
||||
self.item_count,
|
||||
start + (size.y() / item_height).ceil() as usize + 1,
|
||||
);
|
||||
(self.append_items)(start..end, &mut items, ctx.app);
|
||||
(self.append_items)(start..end, &mut items, cx.app);
|
||||
for item in &mut items {
|
||||
item.layout(item_constraint, ctx);
|
||||
item.layout(item_constraint, cx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,10 +175,10 @@ where
|
||||
&mut self,
|
||||
_: Vector2F,
|
||||
layout: &mut Self::LayoutState,
|
||||
ctx: &mut AfterLayoutContext,
|
||||
cx: &mut AfterLayoutContext,
|
||||
) {
|
||||
for item in &mut layout.items {
|
||||
item.after_layout(ctx);
|
||||
item.after_layout(cx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,19 +186,19 @@ where
|
||||
&mut self,
|
||||
bounds: RectF,
|
||||
layout: &mut Self::LayoutState,
|
||||
ctx: &mut PaintContext,
|
||||
cx: &mut PaintContext,
|
||||
) -> Self::PaintState {
|
||||
ctx.scene.push_layer(Some(bounds));
|
||||
cx.scene.push_layer(Some(bounds));
|
||||
|
||||
let mut item_origin =
|
||||
bounds.origin() - vec2f(0.0, self.state.scroll_top() % layout.item_height);
|
||||
|
||||
for item in &mut layout.items {
|
||||
item.paint(item_origin, ctx);
|
||||
item.paint(item_origin, cx);
|
||||
item_origin += vec2f(0.0, layout.item_height);
|
||||
}
|
||||
|
||||
ctx.scene.pop_layer();
|
||||
cx.scene.pop_layer();
|
||||
}
|
||||
|
||||
fn dispatch_event(
|
||||
@@ -207,11 +207,11 @@ where
|
||||
bounds: RectF,
|
||||
layout: &mut Self::LayoutState,
|
||||
_: &mut Self::PaintState,
|
||||
ctx: &mut EventContext,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
let mut handled = false;
|
||||
for item in &mut layout.items {
|
||||
handled = item.dispatch_event(event, ctx) || handled;
|
||||
handled = item.dispatch_event(event, cx) || handled;
|
||||
}
|
||||
|
||||
match event {
|
||||
@@ -221,7 +221,7 @@ where
|
||||
precise,
|
||||
} => {
|
||||
if bounds.contains_point(*position) {
|
||||
if self.scroll(*position, *delta, *precise, layout.scroll_max, ctx) {
|
||||
if self.scroll(*position, *delta, *precise, layout.scroll_max, cx) {
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
@@ -237,14 +237,14 @@ where
|
||||
bounds: RectF,
|
||||
layout: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
ctx: &crate::DebugContext,
|
||||
cx: &crate::DebugContext,
|
||||
) -> json::Value {
|
||||
json!({
|
||||
"type": "UniformList",
|
||||
"bounds": bounds.to_json(),
|
||||
"scroll_max": layout.scroll_max,
|
||||
"item_height": layout.item_height,
|
||||
"items": layout.items.iter().map(|item| item.debug(ctx)).collect::<Vec<json::Value>>()
|
||||
"items": layout.items.iter().map(|item| item.debug(cx)).collect::<Vec<json::Value>>()
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
+15
-21
@@ -98,12 +98,12 @@ impl Matcher {
|
||||
&mut self,
|
||||
keystroke: Keystroke,
|
||||
view_id: usize,
|
||||
ctx: &Context,
|
||||
cx: &Context,
|
||||
) -> MatchResult {
|
||||
let pending = self.pending.entry(view_id).or_default();
|
||||
|
||||
if let Some(pending_ctx) = pending.context.as_ref() {
|
||||
if pending_ctx != ctx {
|
||||
if pending_ctx != cx {
|
||||
pending.keystrokes.clear();
|
||||
}
|
||||
}
|
||||
@@ -113,11 +113,7 @@ impl Matcher {
|
||||
let mut retain_pending = false;
|
||||
for binding in self.keymap.0.iter().rev() {
|
||||
if binding.keystrokes.starts_with(&pending.keystrokes)
|
||||
&& binding
|
||||
.context
|
||||
.as_ref()
|
||||
.map(|c| c.eval(ctx))
|
||||
.unwrap_or(true)
|
||||
&& binding.context.as_ref().map(|c| c.eval(cx)).unwrap_or(true)
|
||||
{
|
||||
if binding.keystrokes.len() == pending.keystrokes.len() {
|
||||
self.pending.remove(&view_id);
|
||||
@@ -127,7 +123,7 @@ impl Matcher {
|
||||
};
|
||||
} else {
|
||||
retain_pending = true;
|
||||
pending.context = Some(ctx.clone());
|
||||
pending.context = Some(cx.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -312,22 +308,20 @@ impl ContextPredicate {
|
||||
}
|
||||
}
|
||||
|
||||
fn eval(&self, ctx: &Context) -> bool {
|
||||
fn eval(&self, cx: &Context) -> bool {
|
||||
match self {
|
||||
Self::Identifier(name) => ctx.set.contains(name.as_str()),
|
||||
Self::Equal(left, right) => ctx
|
||||
Self::Identifier(name) => cx.set.contains(name.as_str()),
|
||||
Self::Equal(left, right) => cx
|
||||
.map
|
||||
.get(left)
|
||||
.map(|value| value == right)
|
||||
.unwrap_or(false),
|
||||
Self::NotEqual(left, right) => ctx
|
||||
.map
|
||||
.get(left)
|
||||
.map(|value| value != right)
|
||||
.unwrap_or(true),
|
||||
Self::Not(pred) => !pred.eval(ctx),
|
||||
Self::And(left, right) => left.eval(ctx) && right.eval(ctx),
|
||||
Self::Or(left, right) => left.eval(ctx) || right.eval(ctx),
|
||||
Self::NotEqual(left, right) => {
|
||||
cx.map.get(left).map(|value| value != right).unwrap_or(true)
|
||||
}
|
||||
Self::Not(pred) => !pred.eval(cx),
|
||||
Self::And(left, right) => left.eval(cx) && right.eval(cx),
|
||||
Self::Or(left, right) => left.eval(cx) || right.eval(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -488,10 +482,10 @@ mod tests {
|
||||
&mut self,
|
||||
keystroke: &str,
|
||||
view_id: usize,
|
||||
ctx: &Context,
|
||||
cx: &Context,
|
||||
) -> Option<(String, Option<A>)> {
|
||||
if let MatchResult::Action { name, arg } =
|
||||
self.push_keystroke(Keystroke::parse(keystroke).unwrap(), view_id, ctx)
|
||||
self.push_keystroke(Keystroke::parse(keystroke).unwrap(), view_id, cx)
|
||||
{
|
||||
Some((name, arg.and_then(|arg| arg.downcast_ref::<A>().cloned())))
|
||||
} else {
|
||||
|
||||
@@ -145,7 +145,7 @@ impl FontSystemState {
|
||||
// Make room for subpixel variants.
|
||||
let bounds = RectI::new(bounds.origin(), bounds.size() + vec2i(1, 1));
|
||||
let mut pixels = vec![0; bounds.width() as usize * bounds.height() as usize];
|
||||
let ctx = CGContext::create_bitmap_context(
|
||||
let cx = CGContext::create_bitmap_context(
|
||||
Some(pixels.as_mut_ptr() as *mut _),
|
||||
bounds.width() as usize,
|
||||
bounds.height() as usize,
|
||||
@@ -157,9 +157,9 @@ impl FontSystemState {
|
||||
|
||||
// Move the origin to bottom left and account for scaling, this
|
||||
// makes drawing text consistent with the font-kit's raster_bounds.
|
||||
ctx.translate(0.0, bounds.height() as CGFloat);
|
||||
cx.translate(0.0, bounds.height() as CGFloat);
|
||||
let transform = scale.translate(-bounds.origin().to_f32());
|
||||
ctx.set_text_matrix(&CGAffineTransform {
|
||||
cx.set_text_matrix(&CGAffineTransform {
|
||||
a: transform.matrix.m11() as CGFloat,
|
||||
b: -transform.matrix.m21() as CGFloat,
|
||||
c: -transform.matrix.m12() as CGFloat,
|
||||
@@ -168,9 +168,9 @@ impl FontSystemState {
|
||||
ty: -transform.vector.y() as CGFloat,
|
||||
});
|
||||
|
||||
ctx.set_font(&font.native_font().copy_to_CGFont());
|
||||
ctx.set_font_size(font_size as CGFloat);
|
||||
ctx.show_glyphs_at_positions(
|
||||
cx.set_font(&font.native_font().copy_to_CGFont());
|
||||
cx.set_font_size(font_size as CGFloat);
|
||||
cx.show_glyphs_at_positions(
|
||||
&[glyph_id as CGGlyph],
|
||||
&[CGPoint::new(
|
||||
(subpixel_shift.x() / scale_factor) as CGFloat,
|
||||
|
||||
+48
-48
@@ -31,11 +31,11 @@ impl Presenter {
|
||||
font_cache: Arc<FontCache>,
|
||||
text_layout_cache: TextLayoutCache,
|
||||
asset_cache: Arc<AssetCache>,
|
||||
app: &MutableAppContext,
|
||||
cx: &MutableAppContext,
|
||||
) -> Self {
|
||||
Self {
|
||||
window_id,
|
||||
rendered_views: app.render_views(window_id),
|
||||
rendered_views: cx.render_views(window_id),
|
||||
parents: HashMap::new(),
|
||||
font_cache,
|
||||
text_layout_cache,
|
||||
@@ -55,7 +55,7 @@ impl Presenter {
|
||||
path
|
||||
}
|
||||
|
||||
pub fn invalidate(&mut self, mut invalidation: WindowInvalidation, app: &AppContext) {
|
||||
pub fn invalidate(&mut self, mut invalidation: WindowInvalidation, cx: &AppContext) {
|
||||
for view_id in invalidation.removed {
|
||||
invalidation.updated.remove(&view_id);
|
||||
self.rendered_views.remove(&view_id);
|
||||
@@ -63,7 +63,7 @@ impl Presenter {
|
||||
}
|
||||
for view_id in invalidation.updated {
|
||||
self.rendered_views
|
||||
.insert(view_id, app.render_view(self.window_id, view_id).unwrap());
|
||||
.insert(view_id, cx.render_view(self.window_id, view_id).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,25 +71,25 @@ impl Presenter {
|
||||
&mut self,
|
||||
window_size: Vector2F,
|
||||
scale_factor: f32,
|
||||
app: &mut MutableAppContext,
|
||||
cx: &mut MutableAppContext,
|
||||
) -> Scene {
|
||||
let mut scene = Scene::new(scale_factor);
|
||||
|
||||
if let Some(root_view_id) = app.root_view_id(self.window_id) {
|
||||
self.layout(window_size, app.as_ref());
|
||||
self.after_layout(app);
|
||||
let mut ctx = PaintContext {
|
||||
if let Some(root_view_id) = cx.root_view_id(self.window_id) {
|
||||
self.layout(window_size, cx.as_ref());
|
||||
self.after_layout(cx);
|
||||
let mut paint_cx = PaintContext {
|
||||
scene: &mut scene,
|
||||
font_cache: &self.font_cache,
|
||||
text_layout_cache: &self.text_layout_cache,
|
||||
rendered_views: &mut self.rendered_views,
|
||||
app: app.as_ref(),
|
||||
app: cx.as_ref(),
|
||||
};
|
||||
ctx.paint(root_view_id, Vector2F::zero());
|
||||
paint_cx.paint(root_view_id, Vector2F::zero());
|
||||
self.text_layout_cache.finish_frame();
|
||||
|
||||
if let Some(event) = self.last_mouse_moved_event.clone() {
|
||||
self.dispatch_event(event, app)
|
||||
self.dispatch_event(event, cx)
|
||||
}
|
||||
} else {
|
||||
log::error!("could not find root_view_id for window {}", self.window_id);
|
||||
@@ -98,8 +98,8 @@ impl Presenter {
|
||||
scene
|
||||
}
|
||||
|
||||
fn layout(&mut self, size: Vector2F, app: &AppContext) {
|
||||
if let Some(root_view_id) = app.root_view_id(self.window_id) {
|
||||
fn layout(&mut self, size: Vector2F, cx: &AppContext) {
|
||||
if let Some(root_view_id) = cx.root_view_id(self.window_id) {
|
||||
let mut layout_ctx = LayoutContext {
|
||||
rendered_views: &mut self.rendered_views,
|
||||
parents: &mut self.parents,
|
||||
@@ -107,49 +107,49 @@ impl Presenter {
|
||||
text_layout_cache: &self.text_layout_cache,
|
||||
asset_cache: &self.asset_cache,
|
||||
view_stack: Vec::new(),
|
||||
app,
|
||||
app: cx,
|
||||
};
|
||||
layout_ctx.layout(root_view_id, SizeConstraint::strict(size));
|
||||
}
|
||||
}
|
||||
|
||||
fn after_layout(&mut self, app: &mut MutableAppContext) {
|
||||
if let Some(root_view_id) = app.root_view_id(self.window_id) {
|
||||
let mut ctx = AfterLayoutContext {
|
||||
fn after_layout(&mut self, cx: &mut MutableAppContext) {
|
||||
if let Some(root_view_id) = cx.root_view_id(self.window_id) {
|
||||
let mut layout_cx = AfterLayoutContext {
|
||||
rendered_views: &mut self.rendered_views,
|
||||
font_cache: &self.font_cache,
|
||||
text_layout_cache: &self.text_layout_cache,
|
||||
app,
|
||||
app: cx,
|
||||
};
|
||||
ctx.after_layout(root_view_id);
|
||||
layout_cx.after_layout(root_view_id);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dispatch_event(&mut self, event: Event, app: &mut MutableAppContext) {
|
||||
if let Some(root_view_id) = app.root_view_id(self.window_id) {
|
||||
pub fn dispatch_event(&mut self, event: Event, cx: &mut MutableAppContext) {
|
||||
if let Some(root_view_id) = cx.root_view_id(self.window_id) {
|
||||
if matches!(event, Event::MouseMoved { .. }) {
|
||||
self.last_mouse_moved_event = Some(event.clone());
|
||||
}
|
||||
|
||||
let mut ctx = EventContext {
|
||||
let mut event_cx = EventContext {
|
||||
rendered_views: &mut self.rendered_views,
|
||||
actions: Default::default(),
|
||||
font_cache: &self.font_cache,
|
||||
text_layout_cache: &self.text_layout_cache,
|
||||
view_stack: Default::default(),
|
||||
invalidated_views: Default::default(),
|
||||
app: app.as_ref(),
|
||||
app: cx.as_ref(),
|
||||
};
|
||||
ctx.dispatch_event(root_view_id, &event);
|
||||
event_cx.dispatch_event(root_view_id, &event);
|
||||
|
||||
let invalidated_views = ctx.invalidated_views;
|
||||
let actions = ctx.actions;
|
||||
let invalidated_views = event_cx.invalidated_views;
|
||||
let actions = event_cx.actions;
|
||||
|
||||
for view_id in invalidated_views {
|
||||
app.notify_view(self.window_id, view_id);
|
||||
cx.notify_view(self.window_id, view_id);
|
||||
}
|
||||
for action in actions {
|
||||
app.dispatch_action_any(
|
||||
cx.dispatch_action_any(
|
||||
self.window_id,
|
||||
&action.path,
|
||||
action.name,
|
||||
@@ -159,14 +159,14 @@ impl Presenter {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn debug_elements(&self, ctx: &AppContext) -> Option<json::Value> {
|
||||
ctx.root_view_id(self.window_id)
|
||||
pub fn debug_elements(&self, cx: &AppContext) -> Option<json::Value> {
|
||||
cx.root_view_id(self.window_id)
|
||||
.and_then(|root_view_id| self.rendered_views.get(&root_view_id))
|
||||
.map(|root_element| {
|
||||
root_element.debug(&DebugContext {
|
||||
rendered_views: &self.rendered_views,
|
||||
font_cache: &self.font_cache,
|
||||
app: ctx,
|
||||
app: cx,
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -380,9 +380,9 @@ impl Element for ChildView {
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
ctx: &mut LayoutContext,
|
||||
cx: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let size = ctx.layout(self.view_id, constraint);
|
||||
let size = cx.layout(self.view_id, constraint);
|
||||
(size, ())
|
||||
}
|
||||
|
||||
@@ -390,18 +390,18 @@ impl Element for ChildView {
|
||||
&mut self,
|
||||
_: Vector2F,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut AfterLayoutContext,
|
||||
cx: &mut AfterLayoutContext,
|
||||
) {
|
||||
ctx.after_layout(self.view_id);
|
||||
cx.after_layout(self.view_id);
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: pathfinder_geometry::rect::RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
ctx: &mut PaintContext,
|
||||
cx: &mut PaintContext,
|
||||
) -> Self::PaintState {
|
||||
ctx.paint(self.view_id, bounds.origin());
|
||||
cx.paint(self.view_id, bounds.origin());
|
||||
}
|
||||
|
||||
fn dispatch_event(
|
||||
@@ -410,9 +410,9 @@ impl Element for ChildView {
|
||||
_: pathfinder_geometry::rect::RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
_: &mut Self::PaintState,
|
||||
ctx: &mut EventContext,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
ctx.dispatch_event(self.view_id, event)
|
||||
cx.dispatch_event(self.view_id, event)
|
||||
}
|
||||
|
||||
fn debug(
|
||||
@@ -420,14 +420,14 @@ impl Element for ChildView {
|
||||
bounds: pathfinder_geometry::rect::RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
ctx: &DebugContext,
|
||||
cx: &DebugContext,
|
||||
) -> serde_json::Value {
|
||||
json!({
|
||||
"type": "ChildView",
|
||||
"view_id": self.view_id,
|
||||
"bounds": bounds.to_json(),
|
||||
"child": if let Some(view) = ctx.rendered_views.get(&self.view_id) {
|
||||
view.debug(ctx)
|
||||
"child": if let Some(view) = cx.rendered_views.get(&self.view_id) {
|
||||
view.debug(cx)
|
||||
} else {
|
||||
json!(null)
|
||||
}
|
||||
@@ -441,9 +441,9 @@ mod tests {
|
||||
// fn test_responder_chain() {
|
||||
// let settings = settings_rx(None);
|
||||
// let mut app = App::new().unwrap();
|
||||
// let workspace = app.add_model(|ctx| Workspace::new(Vec::new(), ctx));
|
||||
// let workspace = app.add_model(|cx| Workspace::new(Vec::new(), cx));
|
||||
// let (window_id, workspace_view) =
|
||||
// app.add_window(|ctx| WorkspaceView::new(workspace.clone(), settings, ctx));
|
||||
// app.add_window(|cx| WorkspaceView::new(workspace.clone(), settings, cx));
|
||||
|
||||
// let invalidations = Rc::new(RefCell::new(Vec::new()));
|
||||
// let invalidations_ = invalidations.clone();
|
||||
@@ -451,8 +451,8 @@ mod tests {
|
||||
// invalidations_.borrow_mut().push(invalidation)
|
||||
// });
|
||||
|
||||
// let active_pane_id = workspace_view.update(&mut app, |view, ctx| {
|
||||
// ctx.focus(view.active_pane());
|
||||
// let active_pane_id = workspace_view.update(&mut app, |view, cx| {
|
||||
// cx.focus(view.active_pane());
|
||||
// view.active_pane().id()
|
||||
// });
|
||||
|
||||
@@ -468,7 +468,7 @@ mod tests {
|
||||
// }
|
||||
|
||||
// assert_eq!(
|
||||
// presenter.responder_chain(app.ctx()).unwrap(),
|
||||
// presenter.responder_chain(app.cx()).unwrap(),
|
||||
// vec![workspace_view.id(), active_pane_id]
|
||||
// );
|
||||
// });
|
||||
|
||||
@@ -200,7 +200,7 @@ impl Line {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn paint(&self, origin: Vector2F, visible_bounds: RectF, ctx: &mut PaintContext) {
|
||||
pub fn paint(&self, origin: Vector2F, visible_bounds: RectF, cx: &mut PaintContext) {
|
||||
let padding_top = (visible_bounds.height() - self.layout.ascent - self.layout.descent) / 2.;
|
||||
let baseline_origin = vec2f(0., padding_top + self.layout.ascent);
|
||||
|
||||
@@ -209,7 +209,7 @@ impl Line {
|
||||
let mut color = ColorU::black();
|
||||
|
||||
for run in &self.layout.runs {
|
||||
let max_glyph_width = ctx
|
||||
let max_glyph_width = cx
|
||||
.font_cache
|
||||
.bounding_box(run.font_id, self.layout.font_size)
|
||||
.x();
|
||||
@@ -234,7 +234,7 @@ impl Line {
|
||||
}
|
||||
}
|
||||
|
||||
ctx.scene.push_glyph(scene::Glyph {
|
||||
cx.scene.push_glyph(scene::Glyph {
|
||||
font_id: run.font_id,
|
||||
font_size: self.layout.font_size,
|
||||
id: glyph.id,
|
||||
|
||||
@@ -34,8 +34,8 @@ pub fn test(args: TokenStream, function: TokenStream) -> TokenStream {
|
||||
fn #outer_fn_name() {
|
||||
#inner_fn
|
||||
|
||||
#namespace::App::test_async((), move |ctx| async {
|
||||
#inner_fn_name(ctx).await;
|
||||
#namespace::App::test_async((), move |cx| async {
|
||||
#inner_fn_name(cx).await;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -45,8 +45,8 @@ pub fn test(args: TokenStream, function: TokenStream) -> TokenStream {
|
||||
fn #outer_fn_name() {
|
||||
#inner_fn
|
||||
|
||||
#namespace::App::test((), |ctx| {
|
||||
#inner_fn_name(ctx);
|
||||
#namespace::App::test((), |cx| {
|
||||
#inner_fn_name(cx);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -81,9 +81,9 @@ impl Selection {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display_range(&self, map: &DisplayMap, app: &AppContext) -> Range<DisplayPoint> {
|
||||
let start = self.start.to_display_point(map, app);
|
||||
let end = self.end.to_display_point(map, app);
|
||||
pub fn display_range(&self, map: &DisplayMap, cx: &AppContext) -> Range<DisplayPoint> {
|
||||
let start = self.start.to_display_point(map, cx);
|
||||
let end = self.end.to_display_point(map, cx);
|
||||
if self.reversed {
|
||||
end..start
|
||||
} else {
|
||||
@@ -95,22 +95,22 @@ impl Selection {
|
||||
&self,
|
||||
include_end_if_at_line_start: bool,
|
||||
map: &DisplayMap,
|
||||
ctx: &AppContext,
|
||||
cx: &AppContext,
|
||||
) -> (Range<u32>, Range<u32>) {
|
||||
let display_start = self.start.to_display_point(map, ctx);
|
||||
let display_start = self.start.to_display_point(map, cx);
|
||||
let buffer_start =
|
||||
DisplayPoint::new(display_start.row(), 0).to_buffer_point(map, Bias::Left, ctx);
|
||||
DisplayPoint::new(display_start.row(), 0).to_buffer_point(map, Bias::Left, cx);
|
||||
|
||||
let mut display_end = self.end.to_display_point(map, ctx);
|
||||
let mut display_end = self.end.to_display_point(map, cx);
|
||||
if !include_end_if_at_line_start
|
||||
&& display_end.row() != map.max_point(ctx).row()
|
||||
&& display_end.row() != map.max_point(cx).row()
|
||||
&& display_start.row() != display_end.row()
|
||||
&& display_end.column() == 0
|
||||
{
|
||||
*display_end.row_mut() -= 1;
|
||||
}
|
||||
let buffer_end = DisplayPoint::new(display_end.row(), map.line_len(display_end.row(), ctx))
|
||||
.to_buffer_point(map, Bias::Left, ctx);
|
||||
let buffer_end = DisplayPoint::new(display_end.row(), map.line_len(display_end.row(), cx))
|
||||
.to_buffer_point(map, Bias::Left, cx);
|
||||
|
||||
(
|
||||
buffer_start.row..buffer_end.row + 1,
|
||||
|
||||
@@ -15,17 +15,17 @@ pub struct DisplayMap {
|
||||
}
|
||||
|
||||
impl DisplayMap {
|
||||
pub fn new(buffer: ModelHandle<Buffer>, tab_size: usize, ctx: &AppContext) -> Self {
|
||||
pub fn new(buffer: ModelHandle<Buffer>, tab_size: usize, cx: &AppContext) -> Self {
|
||||
DisplayMap {
|
||||
buffer: buffer.clone(),
|
||||
fold_map: FoldMap::new(buffer, ctx),
|
||||
fold_map: FoldMap::new(buffer, cx),
|
||||
tab_size,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn snapshot(&self, ctx: &AppContext) -> DisplayMapSnapshot {
|
||||
pub fn snapshot(&self, cx: &AppContext) -> DisplayMapSnapshot {
|
||||
DisplayMapSnapshot {
|
||||
folds_snapshot: self.fold_map.snapshot(ctx),
|
||||
folds_snapshot: self.fold_map.snapshot(cx),
|
||||
tab_size: self.tab_size,
|
||||
}
|
||||
}
|
||||
@@ -33,46 +33,46 @@ impl DisplayMap {
|
||||
pub fn folds_in_range<'a, T>(
|
||||
&'a self,
|
||||
range: Range<T>,
|
||||
app: &'a AppContext,
|
||||
cx: &'a AppContext,
|
||||
) -> impl Iterator<Item = &'a Range<Anchor>>
|
||||
where
|
||||
T: ToOffset,
|
||||
{
|
||||
self.fold_map.folds_in_range(range, app)
|
||||
self.fold_map.folds_in_range(range, cx)
|
||||
}
|
||||
|
||||
pub fn fold<T: ToOffset>(
|
||||
&mut self,
|
||||
ranges: impl IntoIterator<Item = Range<T>>,
|
||||
ctx: &AppContext,
|
||||
cx: &AppContext,
|
||||
) {
|
||||
self.fold_map.fold(ranges, ctx)
|
||||
self.fold_map.fold(ranges, cx)
|
||||
}
|
||||
|
||||
pub fn unfold<T: ToOffset>(
|
||||
&mut self,
|
||||
ranges: impl IntoIterator<Item = Range<T>>,
|
||||
ctx: &AppContext,
|
||||
cx: &AppContext,
|
||||
) {
|
||||
self.fold_map.unfold(ranges, ctx)
|
||||
self.fold_map.unfold(ranges, cx)
|
||||
}
|
||||
|
||||
pub fn intersects_fold<T: ToOffset>(&self, offset: T, ctx: &AppContext) -> bool {
|
||||
self.fold_map.intersects_fold(offset, ctx)
|
||||
pub fn intersects_fold<T: ToOffset>(&self, offset: T, cx: &AppContext) -> bool {
|
||||
self.fold_map.intersects_fold(offset, cx)
|
||||
}
|
||||
|
||||
pub fn is_line_folded(&self, display_row: u32, ctx: &AppContext) -> bool {
|
||||
self.fold_map.is_line_folded(display_row, ctx)
|
||||
pub fn is_line_folded(&self, display_row: u32, cx: &AppContext) -> bool {
|
||||
self.fold_map.is_line_folded(display_row, cx)
|
||||
}
|
||||
|
||||
pub fn text(&self, ctx: &AppContext) -> String {
|
||||
self.snapshot(ctx).chunks_at(DisplayPoint::zero()).collect()
|
||||
pub fn text(&self, cx: &AppContext) -> String {
|
||||
self.snapshot(cx).chunks_at(DisplayPoint::zero()).collect()
|
||||
}
|
||||
|
||||
pub fn line(&self, display_row: u32, ctx: &AppContext) -> String {
|
||||
pub fn line(&self, display_row: u32, cx: &AppContext) -> String {
|
||||
let mut result = String::new();
|
||||
for chunk in self
|
||||
.snapshot(ctx)
|
||||
.snapshot(cx)
|
||||
.chunks_at(DisplayPoint::new(display_row, 0))
|
||||
{
|
||||
if let Some(ix) = chunk.find('\n') {
|
||||
@@ -85,11 +85,11 @@ impl DisplayMap {
|
||||
result
|
||||
}
|
||||
|
||||
pub fn line_indent(&self, display_row: u32, ctx: &AppContext) -> (u32, bool) {
|
||||
pub fn line_indent(&self, display_row: u32, cx: &AppContext) -> (u32, bool) {
|
||||
let mut indent = 0;
|
||||
let mut is_blank = true;
|
||||
for c in self
|
||||
.snapshot(ctx)
|
||||
.snapshot(cx)
|
||||
.chars_at(DisplayPoint::new(display_row, 0))
|
||||
{
|
||||
if c == ' ' {
|
||||
@@ -102,30 +102,30 @@ impl DisplayMap {
|
||||
(indent, is_blank)
|
||||
}
|
||||
|
||||
pub fn line_len(&self, row: u32, ctx: &AppContext) -> u32 {
|
||||
DisplayPoint::new(row, self.fold_map.line_len(row, ctx))
|
||||
.expand_tabs(self, ctx)
|
||||
pub fn line_len(&self, row: u32, cx: &AppContext) -> u32 {
|
||||
DisplayPoint::new(row, self.fold_map.line_len(row, cx))
|
||||
.expand_tabs(self, cx)
|
||||
.column()
|
||||
}
|
||||
|
||||
pub fn max_point(&self, ctx: &AppContext) -> DisplayPoint {
|
||||
self.snapshot(ctx).max_point().expand_tabs(self, ctx)
|
||||
pub fn max_point(&self, cx: &AppContext) -> DisplayPoint {
|
||||
self.snapshot(cx).max_point().expand_tabs(self, cx)
|
||||
}
|
||||
|
||||
pub fn longest_row(&self, ctx: &AppContext) -> u32 {
|
||||
self.fold_map.longest_row(ctx)
|
||||
pub fn longest_row(&self, cx: &AppContext) -> u32 {
|
||||
self.fold_map.longest_row(cx)
|
||||
}
|
||||
|
||||
pub fn anchor_before(&self, point: DisplayPoint, bias: Bias, app: &AppContext) -> Anchor {
|
||||
pub fn anchor_before(&self, point: DisplayPoint, bias: Bias, cx: &AppContext) -> Anchor {
|
||||
self.buffer
|
||||
.read(app)
|
||||
.anchor_before(point.to_buffer_point(self, bias, app))
|
||||
.read(cx)
|
||||
.anchor_before(point.to_buffer_point(self, bias, cx))
|
||||
}
|
||||
|
||||
pub fn anchor_after(&self, point: DisplayPoint, bias: Bias, app: &AppContext) -> Anchor {
|
||||
pub fn anchor_after(&self, point: DisplayPoint, bias: Bias, cx: &AppContext) -> Anchor {
|
||||
self.buffer
|
||||
.read(app)
|
||||
.anchor_after(point.to_buffer_point(self, bias, app))
|
||||
.read(cx)
|
||||
.anchor_after(point.to_buffer_point(self, bias, cx))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,29 +257,29 @@ impl DisplayPoint {
|
||||
&mut self.0.column
|
||||
}
|
||||
|
||||
pub fn to_buffer_point(self, map: &DisplayMap, bias: Bias, ctx: &AppContext) -> Point {
|
||||
pub fn to_buffer_point(self, map: &DisplayMap, bias: Bias, cx: &AppContext) -> Point {
|
||||
map.fold_map
|
||||
.to_buffer_point(self.collapse_tabs(map, bias, ctx), ctx)
|
||||
.to_buffer_point(self.collapse_tabs(map, bias, cx), cx)
|
||||
}
|
||||
|
||||
pub fn to_buffer_offset(self, map: &DisplayMap, bias: Bias, ctx: &AppContext) -> usize {
|
||||
pub fn to_buffer_offset(self, map: &DisplayMap, bias: Bias, cx: &AppContext) -> usize {
|
||||
map.fold_map
|
||||
.to_buffer_offset(self.collapse_tabs(&map, bias, ctx), ctx)
|
||||
.to_buffer_offset(self.collapse_tabs(&map, bias, cx), cx)
|
||||
}
|
||||
|
||||
fn expand_tabs(self, map: &DisplayMap, ctx: &AppContext) -> Self {
|
||||
map.snapshot(ctx).expand_tabs(self)
|
||||
fn expand_tabs(self, map: &DisplayMap, cx: &AppContext) -> Self {
|
||||
map.snapshot(cx).expand_tabs(self)
|
||||
}
|
||||
|
||||
fn collapse_tabs(self, map: &DisplayMap, bias: Bias, ctx: &AppContext) -> Self {
|
||||
map.snapshot(ctx).collapse_tabs(self, bias).0
|
||||
fn collapse_tabs(self, map: &DisplayMap, bias: Bias, cx: &AppContext) -> Self {
|
||||
map.snapshot(cx).collapse_tabs(self, bias).0
|
||||
}
|
||||
}
|
||||
|
||||
impl Point {
|
||||
pub fn to_display_point(self, map: &DisplayMap, ctx: &AppContext) -> DisplayPoint {
|
||||
let mut display_point = map.fold_map.to_display_point(self, ctx);
|
||||
let snapshot = map.fold_map.snapshot(ctx);
|
||||
pub fn to_display_point(self, map: &DisplayMap, cx: &AppContext) -> DisplayPoint {
|
||||
let mut display_point = map.fold_map.to_display_point(self, cx);
|
||||
let snapshot = map.fold_map.snapshot(cx);
|
||||
let chars = snapshot.chars_at(DisplayPoint::new(display_point.row(), 0));
|
||||
*display_point.column_mut() =
|
||||
expand_tabs(chars, display_point.column() as usize, map.tab_size) as u32;
|
||||
@@ -288,9 +288,8 @@ impl Point {
|
||||
}
|
||||
|
||||
impl Anchor {
|
||||
pub fn to_display_point(&self, map: &DisplayMap, app: &AppContext) -> DisplayPoint {
|
||||
self.to_point(map.buffer.read(app))
|
||||
.to_display_point(map, app)
|
||||
pub fn to_display_point(&self, map: &DisplayMap, cx: &AppContext) -> DisplayPoint {
|
||||
self.to_point(map.buffer.read(cx)).to_display_point(map, cx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,12 +462,12 @@ mod tests {
|
||||
use std::sync::Arc;
|
||||
|
||||
#[gpui::test]
|
||||
fn test_chunks_at(app: &mut gpui::MutableAppContext) {
|
||||
fn test_chunks_at(cx: &mut gpui::MutableAppContext) {
|
||||
let text = sample_text(6, 6);
|
||||
let buffer = app.add_model(|ctx| Buffer::new(0, text, ctx));
|
||||
let map = DisplayMap::new(buffer.clone(), 4, app.as_ref());
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
|
||||
let map = DisplayMap::new(buffer.clone(), 4, cx.as_ref());
|
||||
buffer
|
||||
.update(app, |buffer, ctx| {
|
||||
.update(cx, |buffer, cx| {
|
||||
buffer.edit(
|
||||
vec![
|
||||
Point::new(1, 0)..Point::new(1, 0),
|
||||
@@ -476,25 +475,25 @@ mod tests {
|
||||
Point::new(2, 1)..Point::new(2, 1),
|
||||
],
|
||||
"\t",
|
||||
Some(ctx),
|
||||
Some(cx),
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
&map.snapshot(app.as_ref())
|
||||
&map.snapshot(cx.as_ref())
|
||||
.chunks_at(DisplayPoint::new(1, 0))
|
||||
.collect::<String>()[0..10],
|
||||
" b bb"
|
||||
);
|
||||
assert_eq!(
|
||||
&map.snapshot(app.as_ref())
|
||||
&map.snapshot(cx.as_ref())
|
||||
.chunks_at(DisplayPoint::new(1, 2))
|
||||
.collect::<String>()[0..10],
|
||||
" b bbbb"
|
||||
);
|
||||
assert_eq!(
|
||||
&map.snapshot(app.as_ref())
|
||||
&map.snapshot(cx.as_ref())
|
||||
.chunks_at(DisplayPoint::new(1, 6))
|
||||
.collect::<String>()[0..13],
|
||||
" bbbbb\nc c"
|
||||
@@ -502,7 +501,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_highlighted_chunks_at(mut app: gpui::TestAppContext) {
|
||||
async fn test_highlighted_chunks_at(mut cx: gpui::TestAppContext) {
|
||||
use unindent::Unindent as _;
|
||||
|
||||
let grammar = tree_sitter_rust::language();
|
||||
@@ -540,14 +539,14 @@ mod tests {
|
||||
});
|
||||
lang.set_theme(&theme);
|
||||
|
||||
let buffer = app.add_model(|ctx| {
|
||||
Buffer::from_history(0, History::new(text.into()), None, Some(lang), ctx)
|
||||
let buffer = cx.add_model(|cx| {
|
||||
Buffer::from_history(0, History::new(text.into()), None, Some(lang), cx)
|
||||
});
|
||||
buffer.condition(&app, |buf, _| !buf.is_parsing()).await;
|
||||
buffer.condition(&cx, |buf, _| !buf.is_parsing()).await;
|
||||
|
||||
let mut map = app.read(|ctx| DisplayMap::new(buffer, 2, ctx));
|
||||
let mut map = cx.read(|cx| DisplayMap::new(buffer, 2, cx));
|
||||
assert_eq!(
|
||||
app.read(|ctx| highlighted_chunks(0..5, &map, &theme, ctx)),
|
||||
cx.read(|cx| highlighted_chunks(0..5, &map, &theme, cx)),
|
||||
vec![
|
||||
("fn ".to_string(), None),
|
||||
("outer".to_string(), Some("fn.name")),
|
||||
@@ -558,7 +557,7 @@ mod tests {
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
app.read(|ctx| highlighted_chunks(3..5, &map, &theme, ctx)),
|
||||
cx.read(|cx| highlighted_chunks(3..5, &map, &theme, cx)),
|
||||
vec![
|
||||
(" fn ".to_string(), Some("mod.body")),
|
||||
("inner".to_string(), Some("fn.name")),
|
||||
@@ -566,9 +565,9 @@ mod tests {
|
||||
]
|
||||
);
|
||||
|
||||
app.read(|ctx| map.fold(vec![Point::new(0, 6)..Point::new(3, 2)], ctx));
|
||||
cx.read(|cx| map.fold(vec![Point::new(0, 6)..Point::new(3, 2)], cx));
|
||||
assert_eq!(
|
||||
app.read(|ctx| highlighted_chunks(0..2, &map, &theme, ctx)),
|
||||
cx.read(|cx| highlighted_chunks(0..2, &map, &theme, cx)),
|
||||
vec![
|
||||
("fn ".to_string(), None),
|
||||
("out".to_string(), Some("fn.name")),
|
||||
@@ -583,10 +582,10 @@ mod tests {
|
||||
rows: Range<u32>,
|
||||
map: &DisplayMap,
|
||||
theme: &'a Theme,
|
||||
ctx: &AppContext,
|
||||
cx: &AppContext,
|
||||
) -> Vec<(String, Option<&'a str>)> {
|
||||
let mut chunks: Vec<(String, Option<&str>)> = Vec::new();
|
||||
for (chunk, style_id) in map.snapshot(ctx).highlighted_chunks_for_rows(rows) {
|
||||
for (chunk, style_id) in map.snapshot(cx).highlighted_chunks_for_rows(rows) {
|
||||
let style_name = theme.syntax_style_name(style_id);
|
||||
if let Some((last_chunk, last_style_name)) = chunks.last_mut() {
|
||||
if style_name == *last_style_name {
|
||||
@@ -603,17 +602,17 @@ mod tests {
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_clip_point(app: &mut gpui::MutableAppContext) {
|
||||
fn test_clip_point(cx: &mut gpui::MutableAppContext) {
|
||||
use Bias::{Left, Right};
|
||||
|
||||
let text = "\n'a', 'α',\t'✋',\t'❎', '🍐'\n";
|
||||
let display_text = "\n'a', 'α', '✋', '❎', '🍐'\n";
|
||||
let buffer = app.add_model(|ctx| Buffer::new(0, text, ctx));
|
||||
let ctx = app.as_ref();
|
||||
let map = DisplayMap::new(buffer.clone(), 4, ctx);
|
||||
assert_eq!(map.text(ctx), display_text);
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
|
||||
let cx = cx.as_ref();
|
||||
let map = DisplayMap::new(buffer.clone(), 4, cx);
|
||||
assert_eq!(map.text(cx), display_text);
|
||||
|
||||
let map = map.snapshot(ctx);
|
||||
let map = map.snapshot(cx);
|
||||
for (input_column, bias, output_column) in vec![
|
||||
("'a', '".len(), Left, "'a', '".len()),
|
||||
("'a', '".len() + 1, Left, "'a', '".len()),
|
||||
@@ -648,53 +647,53 @@ mod tests {
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_tabs_with_multibyte_chars(app: &mut gpui::MutableAppContext) {
|
||||
fn test_tabs_with_multibyte_chars(cx: &mut gpui::MutableAppContext) {
|
||||
let text = "✅\t\tα\nβ\t\n🏀β\t\tγ";
|
||||
let buffer = app.add_model(|ctx| Buffer::new(0, text, ctx));
|
||||
let ctx = app.as_ref();
|
||||
let map = DisplayMap::new(buffer.clone(), 4, ctx);
|
||||
assert_eq!(map.text(ctx), "✅ α\nβ \n🏀β γ");
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
|
||||
let cx = cx.as_ref();
|
||||
let map = DisplayMap::new(buffer.clone(), 4, cx);
|
||||
assert_eq!(map.text(cx), "✅ α\nβ \n🏀β γ");
|
||||
|
||||
let point = Point::new(0, "✅\t\t".len() as u32);
|
||||
let display_point = DisplayPoint::new(0, "✅ ".len() as u32);
|
||||
assert_eq!(point.to_display_point(&map, ctx), display_point);
|
||||
assert_eq!(display_point.to_buffer_point(&map, Bias::Left, ctx), point,);
|
||||
assert_eq!(point.to_display_point(&map, cx), display_point);
|
||||
assert_eq!(display_point.to_buffer_point(&map, Bias::Left, cx), point,);
|
||||
|
||||
let point = Point::new(1, "β\t".len() as u32);
|
||||
let display_point = DisplayPoint::new(1, "β ".len() as u32);
|
||||
assert_eq!(point.to_display_point(&map, ctx), display_point);
|
||||
assert_eq!(display_point.to_buffer_point(&map, Bias::Left, ctx), point,);
|
||||
assert_eq!(point.to_display_point(&map, cx), display_point);
|
||||
assert_eq!(display_point.to_buffer_point(&map, Bias::Left, cx), point,);
|
||||
|
||||
let point = Point::new(2, "🏀β\t\t".len() as u32);
|
||||
let display_point = DisplayPoint::new(2, "🏀β ".len() as u32);
|
||||
assert_eq!(point.to_display_point(&map, ctx), display_point);
|
||||
assert_eq!(display_point.to_buffer_point(&map, Bias::Left, ctx), point,);
|
||||
assert_eq!(point.to_display_point(&map, cx), display_point);
|
||||
assert_eq!(display_point.to_buffer_point(&map, Bias::Left, cx), point,);
|
||||
|
||||
// Display points inside of expanded tabs
|
||||
assert_eq!(
|
||||
DisplayPoint::new(0, "✅ ".len() as u32).to_buffer_point(&map, Bias::Right, ctx),
|
||||
DisplayPoint::new(0, "✅ ".len() as u32).to_buffer_point(&map, Bias::Right, cx),
|
||||
Point::new(0, "✅\t\t".len() as u32),
|
||||
);
|
||||
assert_eq!(
|
||||
DisplayPoint::new(0, "✅ ".len() as u32).to_buffer_point(&map, Bias::Left, ctx),
|
||||
DisplayPoint::new(0, "✅ ".len() as u32).to_buffer_point(&map, Bias::Left, cx),
|
||||
Point::new(0, "✅\t".len() as u32),
|
||||
);
|
||||
assert_eq!(
|
||||
map.snapshot(ctx)
|
||||
map.snapshot(cx)
|
||||
.chunks_at(DisplayPoint::new(0, "✅ ".len() as u32))
|
||||
.collect::<String>(),
|
||||
" α\nβ \n🏀β γ"
|
||||
);
|
||||
assert_eq!(
|
||||
DisplayPoint::new(0, "✅ ".len() as u32).to_buffer_point(&map, Bias::Right, ctx),
|
||||
DisplayPoint::new(0, "✅ ".len() as u32).to_buffer_point(&map, Bias::Right, cx),
|
||||
Point::new(0, "✅\t".len() as u32),
|
||||
);
|
||||
assert_eq!(
|
||||
DisplayPoint::new(0, "✅ ".len() as u32).to_buffer_point(&map, Bias::Left, ctx),
|
||||
DisplayPoint::new(0, "✅ ".len() as u32).to_buffer_point(&map, Bias::Left, cx),
|
||||
Point::new(0, "✅".len() as u32),
|
||||
);
|
||||
assert_eq!(
|
||||
map.snapshot(ctx)
|
||||
map.snapshot(cx)
|
||||
.chunks_at(DisplayPoint::new(0, "✅ ".len() as u32))
|
||||
.collect::<String>(),
|
||||
" α\nβ \n🏀β γ"
|
||||
@@ -702,21 +701,21 @@ mod tests {
|
||||
|
||||
// Clipping display points inside of multi-byte characters
|
||||
assert_eq!(
|
||||
map.snapshot(ctx)
|
||||
map.snapshot(cx)
|
||||
.clip_point(DisplayPoint::new(0, "✅".len() as u32 - 1), Bias::Left),
|
||||
DisplayPoint::new(0, 0)
|
||||
);
|
||||
assert_eq!(
|
||||
map.snapshot(ctx)
|
||||
map.snapshot(cx)
|
||||
.clip_point(DisplayPoint::new(0, "✅".len() as u32 - 1), Bias::Right),
|
||||
DisplayPoint::new(0, "✅".len() as u32)
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_max_point(app: &mut gpui::MutableAppContext) {
|
||||
let buffer = app.add_model(|ctx| Buffer::new(0, "aaa\n\t\tbbb", ctx));
|
||||
let map = DisplayMap::new(buffer.clone(), 4, app.as_ref());
|
||||
assert_eq!(map.max_point(app.as_ref()), DisplayPoint::new(1, 11))
|
||||
fn test_max_point(cx: &mut gpui::MutableAppContext) {
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, "aaa\n\t\tbbb", cx));
|
||||
let map = DisplayMap::new(buffer.clone(), 4, cx.as_ref());
|
||||
assert_eq!(map.max_point(cx.as_ref()), DisplayPoint::new(1, 11))
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,8 @@ pub struct FoldMap {
|
||||
}
|
||||
|
||||
impl FoldMap {
|
||||
pub fn new(buffer_handle: ModelHandle<Buffer>, ctx: &AppContext) -> Self {
|
||||
let buffer = buffer_handle.read(ctx);
|
||||
pub fn new(buffer_handle: ModelHandle<Buffer>, cx: &AppContext) -> Self {
|
||||
let buffer = buffer_handle.read(cx);
|
||||
let text_summary = buffer.text_summary();
|
||||
Self {
|
||||
buffer: buffer_handle,
|
||||
@@ -43,56 +43,56 @@ impl FoldMap {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn snapshot(&self, ctx: &AppContext) -> FoldMapSnapshot {
|
||||
pub fn snapshot(&self, cx: &AppContext) -> FoldMapSnapshot {
|
||||
FoldMapSnapshot {
|
||||
transforms: self.sync(ctx).clone(),
|
||||
buffer: self.buffer.read(ctx).snapshot(),
|
||||
transforms: self.sync(cx).clone(),
|
||||
buffer: self.buffer.read(cx).snapshot(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self, ctx: &AppContext) -> usize {
|
||||
self.sync(ctx).summary().display.bytes
|
||||
pub fn len(&self, cx: &AppContext) -> usize {
|
||||
self.sync(cx).summary().display.bytes
|
||||
}
|
||||
|
||||
pub fn line_len(&self, row: u32, ctx: &AppContext) -> u32 {
|
||||
let line_start = self.to_display_offset(DisplayPoint::new(row, 0), ctx).0;
|
||||
let line_end = if row >= self.max_point(ctx).row() {
|
||||
self.len(ctx)
|
||||
pub fn line_len(&self, row: u32, cx: &AppContext) -> u32 {
|
||||
let line_start = self.to_display_offset(DisplayPoint::new(row, 0), cx).0;
|
||||
let line_end = if row >= self.max_point(cx).row() {
|
||||
self.len(cx)
|
||||
} else {
|
||||
self.to_display_offset(DisplayPoint::new(row + 1, 0), ctx).0 - 1
|
||||
self.to_display_offset(DisplayPoint::new(row + 1, 0), cx).0 - 1
|
||||
};
|
||||
(line_end - line_start) as u32
|
||||
}
|
||||
|
||||
pub fn max_point(&self, ctx: &AppContext) -> DisplayPoint {
|
||||
DisplayPoint(self.sync(ctx).summary().display.lines)
|
||||
pub fn max_point(&self, cx: &AppContext) -> DisplayPoint {
|
||||
DisplayPoint(self.sync(cx).summary().display.lines)
|
||||
}
|
||||
|
||||
pub fn longest_row(&self, ctx: &AppContext) -> u32 {
|
||||
self.sync(ctx).summary().display.longest_row
|
||||
pub fn longest_row(&self, cx: &AppContext) -> u32 {
|
||||
self.sync(cx).summary().display.longest_row
|
||||
}
|
||||
|
||||
pub fn folds_in_range<'a, T>(
|
||||
&'a self,
|
||||
range: Range<T>,
|
||||
ctx: &'a AppContext,
|
||||
cx: &'a AppContext,
|
||||
) -> impl Iterator<Item = &'a Range<Anchor>>
|
||||
where
|
||||
T: ToOffset,
|
||||
{
|
||||
self.intersecting_folds(range, ctx).map(|f| &f.0)
|
||||
self.intersecting_folds(range, cx).map(|f| &f.0)
|
||||
}
|
||||
|
||||
pub fn fold<T: ToOffset>(
|
||||
&mut self,
|
||||
ranges: impl IntoIterator<Item = Range<T>>,
|
||||
ctx: &AppContext,
|
||||
cx: &AppContext,
|
||||
) {
|
||||
let _ = self.sync(ctx);
|
||||
let _ = self.sync(cx);
|
||||
|
||||
let mut edits = Vec::new();
|
||||
let mut folds = Vec::new();
|
||||
let buffer = self.buffer.read(ctx);
|
||||
let buffer = self.buffer.read(cx);
|
||||
for range in ranges.into_iter() {
|
||||
let range = range.start.to_offset(buffer)..range.end.to_offset(buffer);
|
||||
if range.start != range.end {
|
||||
@@ -124,23 +124,23 @@ impl FoldMap {
|
||||
new_tree.push_tree(cursor.suffix(buffer), buffer);
|
||||
new_tree
|
||||
};
|
||||
self.apply_edits(edits, ctx);
|
||||
self.apply_edits(edits, cx);
|
||||
}
|
||||
|
||||
pub fn unfold<T: ToOffset>(
|
||||
&mut self,
|
||||
ranges: impl IntoIterator<Item = Range<T>>,
|
||||
ctx: &AppContext,
|
||||
cx: &AppContext,
|
||||
) {
|
||||
let _ = self.sync(ctx);
|
||||
let _ = self.sync(cx);
|
||||
|
||||
let buffer = self.buffer.read(ctx);
|
||||
let buffer = self.buffer.read(cx);
|
||||
|
||||
let mut edits = Vec::new();
|
||||
let mut fold_ixs_to_delete = Vec::new();
|
||||
for range in ranges.into_iter() {
|
||||
// Remove intersecting folds and add their ranges to edits that are passed to apply_edits.
|
||||
let mut folds_cursor = self.intersecting_folds(range, ctx);
|
||||
let mut folds_cursor = self.intersecting_folds(range, cx);
|
||||
while let Some(fold) = folds_cursor.item() {
|
||||
let offset_range = fold.0.start.to_offset(buffer)..fold.0.end.to_offset(buffer);
|
||||
edits.push(Edit {
|
||||
@@ -172,18 +172,18 @@ impl FoldMap {
|
||||
folds.push_tree(cursor.suffix(buffer), buffer);
|
||||
folds
|
||||
};
|
||||
self.apply_edits(edits, ctx);
|
||||
self.apply_edits(edits, cx);
|
||||
}
|
||||
|
||||
fn intersecting_folds<'a, T>(
|
||||
&self,
|
||||
range: Range<T>,
|
||||
ctx: &'a AppContext,
|
||||
cx: &'a AppContext,
|
||||
) -> FilterCursor<impl 'a + Fn(&FoldSummary) -> bool, Fold, usize>
|
||||
where
|
||||
T: ToOffset,
|
||||
{
|
||||
let buffer = self.buffer.read(ctx);
|
||||
let buffer = self.buffer.read(cx);
|
||||
let start = buffer.anchor_before(range.start.to_offset(buffer));
|
||||
let end = buffer.anchor_after(range.end.to_offset(buffer));
|
||||
self.folds.filter::<_, usize>(move |summary| {
|
||||
@@ -192,20 +192,20 @@ impl FoldMap {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn intersects_fold<T>(&self, offset: T, ctx: &AppContext) -> bool
|
||||
pub fn intersects_fold<T>(&self, offset: T, cx: &AppContext) -> bool
|
||||
where
|
||||
T: ToOffset,
|
||||
{
|
||||
let buffer = self.buffer.read(ctx);
|
||||
let buffer = self.buffer.read(cx);
|
||||
let offset = offset.to_offset(buffer);
|
||||
let transforms = self.sync(ctx);
|
||||
let transforms = self.sync(cx);
|
||||
let mut cursor = transforms.cursor::<usize, usize>();
|
||||
cursor.seek(&offset, SeekBias::Right, &());
|
||||
cursor.item().map_or(false, |t| t.display_text.is_some())
|
||||
}
|
||||
|
||||
pub fn is_line_folded(&self, display_row: u32, ctx: &AppContext) -> bool {
|
||||
let transforms = self.sync(ctx);
|
||||
pub fn is_line_folded(&self, display_row: u32, cx: &AppContext) -> bool {
|
||||
let transforms = self.sync(cx);
|
||||
let mut cursor = transforms.cursor::<DisplayPoint, DisplayPoint>();
|
||||
cursor.seek(&DisplayPoint::new(display_row, 0), SeekBias::Right, &());
|
||||
while let Some(transform) = cursor.item() {
|
||||
@@ -221,24 +221,24 @@ impl FoldMap {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn to_buffer_offset(&self, point: DisplayPoint, ctx: &AppContext) -> usize {
|
||||
self.snapshot(ctx).to_buffer_offset(point)
|
||||
pub fn to_buffer_offset(&self, point: DisplayPoint, cx: &AppContext) -> usize {
|
||||
self.snapshot(cx).to_buffer_offset(point)
|
||||
}
|
||||
|
||||
pub fn to_display_offset(&self, point: DisplayPoint, ctx: &AppContext) -> DisplayOffset {
|
||||
self.snapshot(ctx).to_display_offset(point)
|
||||
pub fn to_display_offset(&self, point: DisplayPoint, cx: &AppContext) -> DisplayOffset {
|
||||
self.snapshot(cx).to_display_offset(point)
|
||||
}
|
||||
|
||||
pub fn to_buffer_point(&self, display_point: DisplayPoint, ctx: &AppContext) -> Point {
|
||||
let transforms = self.sync(ctx);
|
||||
pub fn to_buffer_point(&self, display_point: DisplayPoint, cx: &AppContext) -> Point {
|
||||
let transforms = self.sync(cx);
|
||||
let mut cursor = transforms.cursor::<DisplayPoint, TransformSummary>();
|
||||
cursor.seek(&display_point, SeekBias::Right, &());
|
||||
let overshoot = display_point.0 - cursor.start().display.lines;
|
||||
cursor.start().buffer.lines + overshoot
|
||||
}
|
||||
|
||||
pub fn to_display_point(&self, point: Point, ctx: &AppContext) -> DisplayPoint {
|
||||
let transforms = self.sync(ctx);
|
||||
pub fn to_display_point(&self, point: Point, cx: &AppContext) -> DisplayPoint {
|
||||
let transforms = self.sync(cx);
|
||||
let mut cursor = transforms.cursor::<Point, TransformSummary>();
|
||||
cursor.seek(&point, SeekBias::Right, &());
|
||||
let overshoot = point - cursor.start().buffer.lines;
|
||||
@@ -248,18 +248,18 @@ impl FoldMap {
|
||||
))
|
||||
}
|
||||
|
||||
fn sync(&self, ctx: &AppContext) -> MutexGuard<SumTree<Transform>> {
|
||||
let buffer = self.buffer.read(ctx);
|
||||
fn sync(&self, cx: &AppContext) -> MutexGuard<SumTree<Transform>> {
|
||||
let buffer = self.buffer.read(cx);
|
||||
let mut edits = buffer.edits_since(self.last_sync.lock().clone()).peekable();
|
||||
if edits.peek().is_some() {
|
||||
self.apply_edits(edits, ctx);
|
||||
self.apply_edits(edits, cx);
|
||||
}
|
||||
*self.last_sync.lock() = buffer.version();
|
||||
self.transforms.lock()
|
||||
}
|
||||
|
||||
fn apply_edits(&self, edits: impl IntoIterator<Item = Edit>, ctx: &AppContext) {
|
||||
let buffer = self.buffer.read(ctx);
|
||||
fn apply_edits(&self, edits: impl IntoIterator<Item = Edit>, cx: &AppContext) {
|
||||
let buffer = self.buffer.read(cx);
|
||||
let mut edits = edits.into_iter().peekable();
|
||||
|
||||
let mut new_transforms = SumTree::new();
|
||||
@@ -846,20 +846,20 @@ mod tests {
|
||||
use crate::test::sample_text;
|
||||
|
||||
#[gpui::test]
|
||||
fn test_basic_folds(app: &mut gpui::MutableAppContext) {
|
||||
let buffer = app.add_model(|ctx| Buffer::new(0, sample_text(5, 6), ctx));
|
||||
let mut map = FoldMap::new(buffer.clone(), app.as_ref());
|
||||
fn test_basic_folds(cx: &mut gpui::MutableAppContext) {
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(5, 6), cx));
|
||||
let mut map = FoldMap::new(buffer.clone(), cx.as_ref());
|
||||
|
||||
map.fold(
|
||||
vec![
|
||||
Point::new(0, 2)..Point::new(2, 2),
|
||||
Point::new(2, 4)..Point::new(4, 1),
|
||||
],
|
||||
app.as_ref(),
|
||||
cx.as_ref(),
|
||||
);
|
||||
assert_eq!(map.text(app.as_ref()), "aa…cc…eeeee");
|
||||
assert_eq!(map.text(cx.as_ref()), "aa…cc…eeeee");
|
||||
|
||||
buffer.update(app, |buffer, ctx| {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer
|
||||
.edit(
|
||||
vec![
|
||||
@@ -867,70 +867,70 @@ mod tests {
|
||||
Point::new(2, 3)..Point::new(2, 3),
|
||||
],
|
||||
"123",
|
||||
Some(ctx),
|
||||
Some(cx),
|
||||
)
|
||||
.unwrap();
|
||||
});
|
||||
assert_eq!(map.text(app.as_ref()), "123a…c123c…eeeee");
|
||||
assert_eq!(map.text(cx.as_ref()), "123a…c123c…eeeee");
|
||||
|
||||
buffer.update(app, |buffer, ctx| {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
let start_version = buffer.version.clone();
|
||||
buffer
|
||||
.edit(Some(Point::new(2, 6)..Point::new(4, 3)), "456", Some(ctx))
|
||||
.edit(Some(Point::new(2, 6)..Point::new(4, 3)), "456", Some(cx))
|
||||
.unwrap();
|
||||
buffer.edits_since(start_version).collect::<Vec<_>>()
|
||||
});
|
||||
assert_eq!(map.text(app.as_ref()), "123a…c123456eee");
|
||||
assert_eq!(map.text(cx.as_ref()), "123a…c123456eee");
|
||||
|
||||
map.unfold(Some(Point::new(0, 4)..Point::new(0, 5)), app.as_ref());
|
||||
assert_eq!(map.text(app.as_ref()), "123aaaaa\nbbbbbb\nccc123456eee");
|
||||
map.unfold(Some(Point::new(0, 4)..Point::new(0, 5)), cx.as_ref());
|
||||
assert_eq!(map.text(cx.as_ref()), "123aaaaa\nbbbbbb\nccc123456eee");
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_adjacent_folds(app: &mut gpui::MutableAppContext) {
|
||||
let buffer = app.add_model(|ctx| Buffer::new(0, "abcdefghijkl", ctx));
|
||||
fn test_adjacent_folds(cx: &mut gpui::MutableAppContext) {
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, "abcdefghijkl", cx));
|
||||
|
||||
{
|
||||
let mut map = FoldMap::new(buffer.clone(), app.as_ref());
|
||||
let mut map = FoldMap::new(buffer.clone(), cx.as_ref());
|
||||
|
||||
map.fold(vec![5..8], app.as_ref());
|
||||
map.check_invariants(app.as_ref());
|
||||
assert_eq!(map.text(app.as_ref()), "abcde…ijkl");
|
||||
map.fold(vec![5..8], cx.as_ref());
|
||||
map.check_invariants(cx.as_ref());
|
||||
assert_eq!(map.text(cx.as_ref()), "abcde…ijkl");
|
||||
|
||||
// Create an fold adjacent to the start of the first fold.
|
||||
map.fold(vec![0..1, 2..5], app.as_ref());
|
||||
map.check_invariants(app.as_ref());
|
||||
assert_eq!(map.text(app.as_ref()), "…b…ijkl");
|
||||
map.fold(vec![0..1, 2..5], cx.as_ref());
|
||||
map.check_invariants(cx.as_ref());
|
||||
assert_eq!(map.text(cx.as_ref()), "…b…ijkl");
|
||||
|
||||
// Create an fold adjacent to the end of the first fold.
|
||||
map.fold(vec![11..11, 8..10], app.as_ref());
|
||||
map.check_invariants(app.as_ref());
|
||||
assert_eq!(map.text(app.as_ref()), "…b…kl");
|
||||
map.fold(vec![11..11, 8..10], cx.as_ref());
|
||||
map.check_invariants(cx.as_ref());
|
||||
assert_eq!(map.text(cx.as_ref()), "…b…kl");
|
||||
}
|
||||
|
||||
{
|
||||
let mut map = FoldMap::new(buffer.clone(), app.as_ref());
|
||||
let mut map = FoldMap::new(buffer.clone(), cx.as_ref());
|
||||
|
||||
// Create two adjacent folds.
|
||||
map.fold(vec![0..2, 2..5], app.as_ref());
|
||||
map.check_invariants(app.as_ref());
|
||||
assert_eq!(map.text(app.as_ref()), "…fghijkl");
|
||||
map.fold(vec![0..2, 2..5], cx.as_ref());
|
||||
map.check_invariants(cx.as_ref());
|
||||
assert_eq!(map.text(cx.as_ref()), "…fghijkl");
|
||||
|
||||
// Edit within one of the folds.
|
||||
buffer.update(app, |buffer, ctx| {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
let version = buffer.version();
|
||||
buffer.edit(vec![0..1], "12345", Some(ctx)).unwrap();
|
||||
buffer.edit(vec![0..1], "12345", Some(cx)).unwrap();
|
||||
buffer.edits_since(version).collect::<Vec<_>>()
|
||||
});
|
||||
map.check_invariants(app.as_ref());
|
||||
assert_eq!(map.text(app.as_ref()), "12345…fghijkl");
|
||||
map.check_invariants(cx.as_ref());
|
||||
assert_eq!(map.text(cx.as_ref()), "12345…fghijkl");
|
||||
}
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_overlapping_folds(app: &mut gpui::MutableAppContext) {
|
||||
let buffer = app.add_model(|ctx| Buffer::new(0, sample_text(5, 6), ctx));
|
||||
let mut map = FoldMap::new(buffer.clone(), app.as_ref());
|
||||
fn test_overlapping_folds(cx: &mut gpui::MutableAppContext) {
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(5, 6), cx));
|
||||
let mut map = FoldMap::new(buffer.clone(), cx.as_ref());
|
||||
map.fold(
|
||||
vec![
|
||||
Point::new(0, 2)..Point::new(2, 2),
|
||||
@@ -938,38 +938,38 @@ mod tests {
|
||||
Point::new(1, 2)..Point::new(3, 2),
|
||||
Point::new(3, 1)..Point::new(4, 1),
|
||||
],
|
||||
app.as_ref(),
|
||||
cx.as_ref(),
|
||||
);
|
||||
assert_eq!(map.text(app.as_ref()), "aa…eeeee");
|
||||
assert_eq!(map.text(cx.as_ref()), "aa…eeeee");
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_merging_folds_via_edit(app: &mut gpui::MutableAppContext) {
|
||||
let buffer = app.add_model(|ctx| Buffer::new(0, sample_text(5, 6), ctx));
|
||||
let mut map = FoldMap::new(buffer.clone(), app.as_ref());
|
||||
fn test_merging_folds_via_edit(cx: &mut gpui::MutableAppContext) {
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(5, 6), cx));
|
||||
let mut map = FoldMap::new(buffer.clone(), cx.as_ref());
|
||||
|
||||
map.fold(
|
||||
vec![
|
||||
Point::new(0, 2)..Point::new(2, 2),
|
||||
Point::new(3, 1)..Point::new(4, 1),
|
||||
],
|
||||
app.as_ref(),
|
||||
cx.as_ref(),
|
||||
);
|
||||
assert_eq!(map.text(app.as_ref()), "aa…cccc\nd…eeeee");
|
||||
assert_eq!(map.text(cx.as_ref()), "aa…cccc\nd…eeeee");
|
||||
|
||||
buffer.update(app, |buffer, ctx| {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer
|
||||
.edit(Some(Point::new(2, 2)..Point::new(3, 1)), "", Some(ctx))
|
||||
.edit(Some(Point::new(2, 2)..Point::new(3, 1)), "", Some(cx))
|
||||
.unwrap();
|
||||
});
|
||||
assert_eq!(map.text(app.as_ref()), "aa…eeeee");
|
||||
assert_eq!(map.text(cx.as_ref()), "aa…eeeee");
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_folds_in_range(app: &mut gpui::MutableAppContext) {
|
||||
let buffer = app.add_model(|ctx| Buffer::new(0, sample_text(5, 6), ctx));
|
||||
let mut map = FoldMap::new(buffer.clone(), app.as_ref());
|
||||
let buffer = buffer.read(app);
|
||||
fn test_folds_in_range(cx: &mut gpui::MutableAppContext) {
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(5, 6), cx));
|
||||
let mut map = FoldMap::new(buffer.clone(), cx.as_ref());
|
||||
let buffer = buffer.read(cx);
|
||||
|
||||
map.fold(
|
||||
vec![
|
||||
@@ -978,10 +978,10 @@ mod tests {
|
||||
Point::new(1, 2)..Point::new(3, 2),
|
||||
Point::new(3, 1)..Point::new(4, 1),
|
||||
],
|
||||
app.as_ref(),
|
||||
cx.as_ref(),
|
||||
);
|
||||
let fold_ranges = map
|
||||
.folds_in_range(Point::new(1, 0)..Point::new(1, 3), app.as_ref())
|
||||
.folds_in_range(Point::new(1, 0)..Point::new(1, 3), cx.as_ref())
|
||||
.map(|fold| fold.start.to_point(buffer)..fold.end.to_point(buffer))
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
@@ -994,7 +994,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_random_folds(app: &mut gpui::MutableAppContext) {
|
||||
fn test_random_folds(cx: &mut gpui::MutableAppContext) {
|
||||
use crate::editor::ToPoint;
|
||||
use crate::util::RandomCharIter;
|
||||
use rand::prelude::*;
|
||||
@@ -1018,18 +1018,18 @@ mod tests {
|
||||
dbg!(seed);
|
||||
let mut rng = StdRng::seed_from_u64(seed);
|
||||
|
||||
let buffer = app.add_model(|ctx| {
|
||||
let buffer = cx.add_model(|cx| {
|
||||
let len = rng.gen_range(0..10);
|
||||
let text = RandomCharIter::new(&mut rng).take(len).collect::<String>();
|
||||
Buffer::new(0, text, ctx)
|
||||
Buffer::new(0, text, cx)
|
||||
});
|
||||
let mut map = FoldMap::new(buffer.clone(), app.as_ref());
|
||||
let mut map = FoldMap::new(buffer.clone(), cx.as_ref());
|
||||
|
||||
for _ in 0..operations {
|
||||
log::info!("text: {:?}", buffer.read(app).text());
|
||||
log::info!("text: {:?}", buffer.read(cx).text());
|
||||
match rng.gen_range(0..=100) {
|
||||
0..=34 => {
|
||||
let buffer = buffer.read(app);
|
||||
let buffer = buffer.read(cx);
|
||||
let mut to_fold = Vec::new();
|
||||
for _ in 0..rng.gen_range(1..=5) {
|
||||
let end = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Right);
|
||||
@@ -1037,10 +1037,10 @@ mod tests {
|
||||
to_fold.push(start..end);
|
||||
}
|
||||
log::info!("folding {:?}", to_fold);
|
||||
map.fold(to_fold, app.as_ref());
|
||||
map.fold(to_fold, cx.as_ref());
|
||||
}
|
||||
35..=59 if !map.folds.is_empty() => {
|
||||
let buffer = buffer.read(app);
|
||||
let buffer = buffer.read(cx);
|
||||
let mut to_unfold = Vec::new();
|
||||
for _ in 0..rng.gen_range(1..=3) {
|
||||
let end = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Right);
|
||||
@@ -1048,25 +1048,25 @@ mod tests {
|
||||
to_unfold.push(start..end);
|
||||
}
|
||||
log::info!("unfolding {:?}", to_unfold);
|
||||
map.unfold(to_unfold, app.as_ref());
|
||||
map.unfold(to_unfold, cx.as_ref());
|
||||
}
|
||||
_ => {
|
||||
let edits = buffer.update(app, |buffer, ctx| {
|
||||
let edits = buffer.update(cx, |buffer, cx| {
|
||||
let start_version = buffer.version.clone();
|
||||
let edit_count = rng.gen_range(1..=5);
|
||||
buffer.randomly_edit(&mut rng, edit_count, Some(ctx));
|
||||
buffer.randomly_edit(&mut rng, edit_count, Some(cx));
|
||||
buffer.edits_since(start_version).collect::<Vec<_>>()
|
||||
});
|
||||
log::info!("editing {:?}", edits);
|
||||
}
|
||||
}
|
||||
map.check_invariants(app.as_ref());
|
||||
map.check_invariants(cx.as_ref());
|
||||
|
||||
let buffer = map.buffer.read(app);
|
||||
let buffer = map.buffer.read(cx);
|
||||
let mut expected_text = buffer.text();
|
||||
let mut expected_buffer_rows = Vec::new();
|
||||
let mut next_row = buffer.max_point().row;
|
||||
for fold_range in map.merged_fold_ranges(app.as_ref()).into_iter().rev() {
|
||||
for fold_range in map.merged_fold_ranges(cx.as_ref()).into_iter().rev() {
|
||||
let fold_start = buffer.point_for_offset(fold_range.start).unwrap();
|
||||
let fold_end = buffer.point_for_offset(fold_range.end).unwrap();
|
||||
expected_buffer_rows.extend((fold_end.row + 1..=next_row).rev());
|
||||
@@ -1077,14 +1077,14 @@ mod tests {
|
||||
expected_buffer_rows.extend((0..=next_row).rev());
|
||||
expected_buffer_rows.reverse();
|
||||
|
||||
assert_eq!(map.text(app.as_ref()), expected_text);
|
||||
assert_eq!(map.text(cx.as_ref()), expected_text);
|
||||
|
||||
for (display_row, line) in expected_text.lines().enumerate() {
|
||||
let line_len = map.line_len(display_row as u32, app.as_ref());
|
||||
let line_len = map.line_len(display_row as u32, cx.as_ref());
|
||||
assert_eq!(line_len, line.len() as u32);
|
||||
}
|
||||
|
||||
let longest_row = map.longest_row(app.as_ref());
|
||||
let longest_row = map.longest_row(cx.as_ref());
|
||||
let longest_char_column = expected_text
|
||||
.split('\n')
|
||||
.nth(longest_row as usize)
|
||||
@@ -1095,22 +1095,22 @@ mod tests {
|
||||
let mut display_offset = DisplayOffset(0);
|
||||
let mut char_column = 0;
|
||||
for c in expected_text.chars() {
|
||||
let buffer_point = map.to_buffer_point(display_point, app.as_ref());
|
||||
let buffer_point = map.to_buffer_point(display_point, cx.as_ref());
|
||||
let buffer_offset = buffer_point.to_offset(buffer);
|
||||
assert_eq!(
|
||||
map.to_display_point(buffer_point, app.as_ref()),
|
||||
map.to_display_point(buffer_point, cx.as_ref()),
|
||||
display_point,
|
||||
"to_display_point({:?})",
|
||||
buffer_point,
|
||||
);
|
||||
assert_eq!(
|
||||
map.to_buffer_offset(display_point, app.as_ref()),
|
||||
map.to_buffer_offset(display_point, cx.as_ref()),
|
||||
buffer_offset,
|
||||
"to_buffer_offset({:?})",
|
||||
display_point,
|
||||
);
|
||||
assert_eq!(
|
||||
map.to_display_offset(display_point, app.as_ref()),
|
||||
map.to_display_offset(display_point, cx.as_ref()),
|
||||
display_offset,
|
||||
"to_display_offset({:?})",
|
||||
display_point,
|
||||
@@ -1137,12 +1137,12 @@ mod tests {
|
||||
}
|
||||
|
||||
for _ in 0..5 {
|
||||
let offset = map.snapshot(app.as_ref()).clip_offset(
|
||||
DisplayOffset(rng.gen_range(0..=map.len(app.as_ref()))),
|
||||
let offset = map.snapshot(cx.as_ref()).clip_offset(
|
||||
DisplayOffset(rng.gen_range(0..=map.len(cx.as_ref()))),
|
||||
Bias::Right,
|
||||
);
|
||||
assert_eq!(
|
||||
map.snapshot(app.as_ref())
|
||||
map.snapshot(cx.as_ref())
|
||||
.chunks_at(offset)
|
||||
.collect::<String>(),
|
||||
&expected_text[offset.0..],
|
||||
@@ -1151,20 +1151,20 @@ mod tests {
|
||||
|
||||
for (idx, buffer_row) in expected_buffer_rows.iter().enumerate() {
|
||||
let display_row = map
|
||||
.to_display_point(Point::new(*buffer_row, 0), app.as_ref())
|
||||
.to_display_point(Point::new(*buffer_row, 0), cx.as_ref())
|
||||
.row();
|
||||
assert_eq!(
|
||||
map.snapshot(app.as_ref())
|
||||
map.snapshot(cx.as_ref())
|
||||
.buffer_rows(display_row)
|
||||
.collect::<Vec<_>>(),
|
||||
expected_buffer_rows[idx..],
|
||||
);
|
||||
}
|
||||
|
||||
for fold_range in map.merged_fold_ranges(app.as_ref()) {
|
||||
for fold_range in map.merged_fold_ranges(cx.as_ref()) {
|
||||
let display_point =
|
||||
map.to_display_point(fold_range.start.to_point(buffer), app.as_ref());
|
||||
assert!(map.is_line_folded(display_point.row(), app.as_ref()));
|
||||
map.to_display_point(fold_range.start.to_point(buffer), cx.as_ref());
|
||||
assert!(map.is_line_folded(display_point.row(), cx.as_ref()));
|
||||
}
|
||||
|
||||
for _ in 0..5 {
|
||||
@@ -1184,7 +1184,7 @@ mod tests {
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(
|
||||
map.folds_in_range(start..end, app.as_ref())
|
||||
map.folds_in_range(start..end, cx.as_ref())
|
||||
.cloned()
|
||||
.collect::<Vec<_>>(),
|
||||
expected_folds
|
||||
@@ -1195,42 +1195,38 @@ mod tests {
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_buffer_rows(app: &mut gpui::MutableAppContext) {
|
||||
fn test_buffer_rows(cx: &mut gpui::MutableAppContext) {
|
||||
let text = sample_text(6, 6) + "\n";
|
||||
let buffer = app.add_model(|ctx| Buffer::new(0, text, ctx));
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
|
||||
|
||||
let mut map = FoldMap::new(buffer.clone(), app.as_ref());
|
||||
let mut map = FoldMap::new(buffer.clone(), cx.as_ref());
|
||||
|
||||
map.fold(
|
||||
vec![
|
||||
Point::new(0, 2)..Point::new(2, 2),
|
||||
Point::new(3, 1)..Point::new(4, 1),
|
||||
],
|
||||
app.as_ref(),
|
||||
cx.as_ref(),
|
||||
);
|
||||
|
||||
assert_eq!(map.text(app.as_ref()), "aa…cccc\nd…eeeee\nffffff\n");
|
||||
assert_eq!(map.text(cx.as_ref()), "aa…cccc\nd…eeeee\nffffff\n");
|
||||
assert_eq!(
|
||||
map.snapshot(app.as_ref())
|
||||
.buffer_rows(0)
|
||||
.collect::<Vec<_>>(),
|
||||
map.snapshot(cx.as_ref()).buffer_rows(0).collect::<Vec<_>>(),
|
||||
vec![0, 3, 5, 6]
|
||||
);
|
||||
assert_eq!(
|
||||
map.snapshot(app.as_ref())
|
||||
.buffer_rows(3)
|
||||
.collect::<Vec<_>>(),
|
||||
map.snapshot(cx.as_ref()).buffer_rows(3).collect::<Vec<_>>(),
|
||||
vec![6]
|
||||
);
|
||||
}
|
||||
|
||||
impl FoldMap {
|
||||
fn text(&self, app: &AppContext) -> String {
|
||||
self.snapshot(app).chunks_at(DisplayOffset(0)).collect()
|
||||
fn text(&self, cx: &AppContext) -> String {
|
||||
self.snapshot(cx).chunks_at(DisplayOffset(0)).collect()
|
||||
}
|
||||
|
||||
fn merged_fold_ranges(&self, app: &AppContext) -> Vec<Range<usize>> {
|
||||
let buffer = self.buffer.read(app);
|
||||
fn merged_fold_ranges(&self, cx: &AppContext) -> Vec<Range<usize>> {
|
||||
let buffer = self.buffer.read(cx);
|
||||
let mut folds = self.folds.items();
|
||||
// Ensure sorting doesn't change how folds get merged and displayed.
|
||||
folds.sort_by(|a, b| a.0.cmp(&b.0, buffer).unwrap());
|
||||
@@ -1258,9 +1254,9 @@ mod tests {
|
||||
merged_ranges
|
||||
}
|
||||
|
||||
fn check_invariants(&self, ctx: &AppContext) {
|
||||
let transforms = self.sync(ctx);
|
||||
let buffer = self.buffer.read(ctx);
|
||||
fn check_invariants(&self, cx: &AppContext) {
|
||||
let transforms = self.sync(cx);
|
||||
let buffer = self.buffer.read(cx);
|
||||
assert_eq!(
|
||||
transforms.summary().buffer.bytes,
|
||||
buffer.len(),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{BufferView, DisplayPoint, SelectAction};
|
||||
use super::{DisplayPoint, Editor, SelectAction};
|
||||
use gpui::{
|
||||
color::{ColorF, ColorU},
|
||||
geometry::{
|
||||
@@ -16,17 +16,17 @@ use smallvec::SmallVec;
|
||||
use std::cmp::Ordering;
|
||||
use std::cmp::{self};
|
||||
|
||||
pub struct BufferElement {
|
||||
view: WeakViewHandle<BufferView>,
|
||||
pub struct EditorElement {
|
||||
view: WeakViewHandle<Editor>,
|
||||
}
|
||||
|
||||
impl BufferElement {
|
||||
pub fn new(view: WeakViewHandle<BufferView>) -> Self {
|
||||
impl EditorElement {
|
||||
pub fn new(view: WeakViewHandle<Editor>) -> Self {
|
||||
Self { view }
|
||||
}
|
||||
|
||||
fn view<'a>(&self, ctx: &'a AppContext) -> &'a BufferView {
|
||||
self.view.upgrade(ctx).unwrap().read(ctx)
|
||||
fn view<'a>(&self, cx: &'a AppContext) -> &'a Editor {
|
||||
self.view.upgrade(cx).unwrap().read(cx)
|
||||
}
|
||||
|
||||
fn mouse_down(
|
||||
@@ -35,22 +35,21 @@ impl BufferElement {
|
||||
cmd: bool,
|
||||
layout: &mut LayoutState,
|
||||
paint: &mut PaintState,
|
||||
ctx: &mut EventContext,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
if paint.text_bounds.contains_point(position) {
|
||||
let view = self.view(ctx.app);
|
||||
let position =
|
||||
paint.point_for_position(view, layout, position, ctx.font_cache, ctx.app);
|
||||
ctx.dispatch_action("buffer:select", SelectAction::Begin { position, add: cmd });
|
||||
let view = self.view(cx.app);
|
||||
let position = paint.point_for_position(view, layout, position, cx.font_cache, cx.app);
|
||||
cx.dispatch_action("buffer:select", SelectAction::Begin { position, add: cmd });
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn mouse_up(&self, _position: Vector2F, ctx: &mut EventContext) -> bool {
|
||||
if self.view(ctx.app).is_selecting() {
|
||||
ctx.dispatch_action("buffer:select", SelectAction::End);
|
||||
fn mouse_up(&self, _position: Vector2F, cx: &mut EventContext) -> bool {
|
||||
if self.view(cx.app).is_selecting() {
|
||||
cx.dispatch_action("buffer:select", SelectAction::End);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@@ -62,15 +61,15 @@ impl BufferElement {
|
||||
position: Vector2F,
|
||||
layout: &mut LayoutState,
|
||||
paint: &mut PaintState,
|
||||
ctx: &mut EventContext,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
let view = self.view(ctx.app);
|
||||
let view = self.view(cx.app);
|
||||
|
||||
if view.is_selecting() {
|
||||
let rect = paint.text_bounds;
|
||||
let mut scroll_delta = Vector2F::zero();
|
||||
|
||||
let vertical_margin = view.line_height(ctx.font_cache).min(rect.height() / 3.0);
|
||||
let vertical_margin = view.line_height(cx.font_cache).min(rect.height() / 3.0);
|
||||
let top = rect.origin_y() + vertical_margin;
|
||||
let bottom = rect.lower_left().y() - vertical_margin;
|
||||
if position.y() < top {
|
||||
@@ -80,7 +79,7 @@ impl BufferElement {
|
||||
scroll_delta.set_y(scale_vertical_mouse_autoscroll_delta(position.y() - bottom))
|
||||
}
|
||||
|
||||
let horizontal_margin = view.line_height(ctx.font_cache).min(rect.width() / 3.0);
|
||||
let horizontal_margin = view.line_height(cx.font_cache).min(rect.width() / 3.0);
|
||||
let left = rect.origin_x() + horizontal_margin;
|
||||
let right = rect.upper_right().x() - horizontal_margin;
|
||||
if position.x() < left {
|
||||
@@ -94,19 +93,19 @@ impl BufferElement {
|
||||
))
|
||||
}
|
||||
|
||||
ctx.dispatch_action(
|
||||
cx.dispatch_action(
|
||||
"buffer:select",
|
||||
SelectAction::Update {
|
||||
position: paint.point_for_position(
|
||||
view,
|
||||
layout,
|
||||
position,
|
||||
ctx.font_cache,
|
||||
ctx.app,
|
||||
cx.font_cache,
|
||||
cx.app,
|
||||
),
|
||||
scroll_position: (view.scroll_position() + scroll_delta).clamp(
|
||||
Vector2F::zero(),
|
||||
layout.scroll_max(view, ctx.font_cache, ctx.text_layout_cache, ctx.app),
|
||||
layout.scroll_max(view, cx.font_cache, cx.text_layout_cache, cx.app),
|
||||
),
|
||||
},
|
||||
);
|
||||
@@ -116,17 +115,17 @@ impl BufferElement {
|
||||
}
|
||||
}
|
||||
|
||||
fn key_down(&self, chars: &str, ctx: &mut EventContext) -> bool {
|
||||
let view = self.view.upgrade(ctx.app).unwrap();
|
||||
fn key_down(&self, chars: &str, cx: &mut EventContext) -> bool {
|
||||
let view = self.view.upgrade(cx.app).unwrap();
|
||||
|
||||
if view.is_focused(ctx.app) {
|
||||
if view.is_focused(cx.app) {
|
||||
if chars.is_empty() {
|
||||
false
|
||||
} else {
|
||||
if chars.chars().any(|c| c.is_control()) {
|
||||
false
|
||||
} else {
|
||||
ctx.dispatch_action("buffer:insert", chars.to_string());
|
||||
cx.dispatch_action("buffer:insert", chars.to_string());
|
||||
true
|
||||
}
|
||||
}
|
||||
@@ -142,15 +141,15 @@ impl BufferElement {
|
||||
precise: bool,
|
||||
layout: &mut LayoutState,
|
||||
paint: &mut PaintState,
|
||||
ctx: &mut EventContext,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
if !paint.bounds.contains_point(position) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let view = self.view(ctx.app);
|
||||
let font_cache = &ctx.font_cache;
|
||||
let layout_cache = &ctx.text_layout_cache;
|
||||
let view = self.view(cx.app);
|
||||
let font_cache = &cx.font_cache;
|
||||
let layout_cache = &cx.text_layout_cache;
|
||||
let max_glyph_width = view.em_width(font_cache);
|
||||
let line_height = view.line_height(font_cache);
|
||||
if !precise {
|
||||
@@ -161,21 +160,21 @@ impl BufferElement {
|
||||
let y = (view.scroll_position().y() * line_height - delta.y()) / line_height;
|
||||
let scroll_position = vec2f(x, y).clamp(
|
||||
Vector2F::zero(),
|
||||
layout.scroll_max(view, font_cache, layout_cache, ctx.app),
|
||||
layout.scroll_max(view, font_cache, layout_cache, cx.app),
|
||||
);
|
||||
|
||||
ctx.dispatch_action("buffer:scroll", scroll_position);
|
||||
cx.dispatch_action("buffer:scroll", scroll_position);
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn paint_gutter(&mut self, rect: RectF, layout: &LayoutState, ctx: &mut PaintContext) {
|
||||
let view = self.view(ctx.app);
|
||||
let line_height = view.line_height(ctx.font_cache);
|
||||
fn paint_gutter(&mut self, rect: RectF, layout: &LayoutState, cx: &mut PaintContext) {
|
||||
let view = self.view(cx.app);
|
||||
let line_height = view.line_height(cx.font_cache);
|
||||
let scroll_top = view.scroll_position().y() * line_height;
|
||||
|
||||
ctx.scene.push_layer(Some(rect));
|
||||
ctx.scene.push_quad(Quad {
|
||||
cx.scene.push_layer(Some(rect));
|
||||
cx.scene.push_quad(Quad {
|
||||
bounds: rect,
|
||||
background: Some(ColorU::white()),
|
||||
border: Border::new(0., ColorU::transparent_black()),
|
||||
@@ -191,25 +190,25 @@ impl BufferElement {
|
||||
line.paint(
|
||||
line_origin,
|
||||
RectF::new(vec2f(0., 0.), vec2f(line.width(), line_height)),
|
||||
ctx,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
|
||||
ctx.scene.pop_layer();
|
||||
cx.scene.pop_layer();
|
||||
}
|
||||
|
||||
fn paint_text(&mut self, bounds: RectF, layout: &LayoutState, ctx: &mut PaintContext) {
|
||||
let view = self.view(ctx.app);
|
||||
let line_height = view.line_height(ctx.font_cache);
|
||||
let descent = view.font_descent(ctx.font_cache);
|
||||
fn paint_text(&mut self, bounds: RectF, layout: &LayoutState, cx: &mut PaintContext) {
|
||||
let view = self.view(cx.app);
|
||||
let line_height = view.line_height(cx.font_cache);
|
||||
let descent = view.font_descent(cx.font_cache);
|
||||
let start_row = view.scroll_position().y() as u32;
|
||||
let scroll_top = view.scroll_position().y() * line_height;
|
||||
let end_row = ((scroll_top + bounds.height()) / line_height).ceil() as u32 + 1; // Add 1 to ensure selections bleed off screen
|
||||
let max_glyph_width = view.em_width(ctx.font_cache);
|
||||
let max_glyph_width = view.em_width(cx.font_cache);
|
||||
let scroll_left = view.scroll_position().x() * max_glyph_width;
|
||||
|
||||
ctx.scene.push_layer(Some(bounds));
|
||||
ctx.scene.push_quad(Quad {
|
||||
cx.scene.push_layer(Some(bounds));
|
||||
cx.scene.push_quad(Quad {
|
||||
bounds,
|
||||
background: Some(ColorU::white()),
|
||||
border: Border::new(0., ColorU::transparent_black()),
|
||||
@@ -224,7 +223,7 @@ impl BufferElement {
|
||||
|
||||
for selection in view.selections_in_range(
|
||||
DisplayPoint::new(start_row, 0)..DisplayPoint::new(end_row, 0),
|
||||
ctx.app,
|
||||
cx.app,
|
||||
) {
|
||||
if selection.start != selection.end {
|
||||
let range_start = cmp::min(selection.start, selection.end);
|
||||
@@ -263,7 +262,7 @@ impl BufferElement {
|
||||
.collect(),
|
||||
};
|
||||
|
||||
selection.paint(bounds, ctx.scene);
|
||||
selection.paint(bounds, cx.scene);
|
||||
}
|
||||
|
||||
if view.cursors_visible() {
|
||||
@@ -288,49 +287,49 @@ impl BufferElement {
|
||||
line.paint(
|
||||
content_origin + vec2f(-scroll_left, row as f32 * line_height - scroll_top),
|
||||
RectF::new(vec2f(scroll_left, 0.), vec2f(bounds.width(), line_height)),
|
||||
ctx,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
|
||||
ctx.scene.push_layer(Some(bounds));
|
||||
cx.scene.push_layer(Some(bounds));
|
||||
for cursor in cursors {
|
||||
cursor.paint(ctx);
|
||||
cursor.paint(cx);
|
||||
}
|
||||
ctx.scene.pop_layer();
|
||||
cx.scene.pop_layer();
|
||||
|
||||
ctx.scene.pop_layer();
|
||||
cx.scene.pop_layer();
|
||||
}
|
||||
}
|
||||
|
||||
impl Element for BufferElement {
|
||||
impl Element for EditorElement {
|
||||
type LayoutState = Option<LayoutState>;
|
||||
type PaintState = Option<PaintState>;
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
ctx: &mut LayoutContext,
|
||||
cx: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let app = ctx.app;
|
||||
let app = cx.app;
|
||||
let mut size = constraint.max;
|
||||
if size.y().is_infinite() {
|
||||
let view = self.view(app);
|
||||
size.set_y((view.max_point(app).row() + 1) as f32 * view.line_height(ctx.font_cache));
|
||||
size.set_y((view.max_point(app).row() + 1) as f32 * view.line_height(cx.font_cache));
|
||||
}
|
||||
if size.x().is_infinite() {
|
||||
unimplemented!("we don't yet handle an infinite width constraint on buffer elements");
|
||||
}
|
||||
|
||||
let view = self.view(app);
|
||||
let font_cache = &ctx.font_cache;
|
||||
let layout_cache = &ctx.text_layout_cache;
|
||||
let font_cache = &cx.font_cache;
|
||||
let layout_cache = &cx.text_layout_cache;
|
||||
let line_height = view.line_height(font_cache);
|
||||
|
||||
let gutter_padding;
|
||||
let gutter_width;
|
||||
if view.is_gutter_visible() {
|
||||
gutter_padding = view.em_width(ctx.font_cache);
|
||||
match view.max_line_number_width(ctx.font_cache, ctx.text_layout_cache, app) {
|
||||
gutter_padding = view.em_width(cx.font_cache);
|
||||
match view.max_line_number_width(cx.font_cache, cx.text_layout_cache, app) {
|
||||
Err(error) => {
|
||||
log::error!("error computing max line number width: {}", error);
|
||||
return (size, None);
|
||||
@@ -348,7 +347,7 @@ impl Element for BufferElement {
|
||||
let autoscroll_horizontally = view.autoscroll_vertically(size.y(), line_height, app);
|
||||
|
||||
let line_number_layouts = if view.is_gutter_visible() {
|
||||
match view.layout_line_numbers(size.y(), ctx.font_cache, ctx.text_layout_cache, app) {
|
||||
match view.layout_line_numbers(size.y(), cx.font_cache, cx.text_layout_cache, app) {
|
||||
Err(error) => {
|
||||
log::error!("error laying out line numbers: {}", error);
|
||||
return (size, None);
|
||||
@@ -400,15 +399,15 @@ impl Element for BufferElement {
|
||||
&mut self,
|
||||
_: Vector2F,
|
||||
layout: &mut Option<LayoutState>,
|
||||
ctx: &mut AfterLayoutContext,
|
||||
cx: &mut AfterLayoutContext,
|
||||
) {
|
||||
if let Some(layout) = layout {
|
||||
let app = ctx.app.as_ref();
|
||||
let app = cx.app.as_ref();
|
||||
|
||||
let view = self.view(app);
|
||||
view.clamp_scroll_left(
|
||||
layout
|
||||
.scroll_max(view, ctx.font_cache, ctx.text_layout_cache, app)
|
||||
.scroll_max(view, cx.font_cache, cx.text_layout_cache, app)
|
||||
.x(),
|
||||
);
|
||||
|
||||
@@ -416,8 +415,8 @@ impl Element for BufferElement {
|
||||
view.autoscroll_horizontally(
|
||||
view.scroll_position().y() as u32,
|
||||
layout.text_size.x(),
|
||||
layout.scroll_width(view, ctx.font_cache, ctx.text_layout_cache, app),
|
||||
view.em_width(ctx.font_cache),
|
||||
layout.scroll_width(view, cx.font_cache, cx.text_layout_cache, app),
|
||||
view.em_width(cx.font_cache),
|
||||
&layout.line_layouts,
|
||||
app,
|
||||
);
|
||||
@@ -429,7 +428,7 @@ impl Element for BufferElement {
|
||||
&mut self,
|
||||
bounds: RectF,
|
||||
layout: &mut Self::LayoutState,
|
||||
ctx: &mut PaintContext,
|
||||
cx: &mut PaintContext,
|
||||
) -> Self::PaintState {
|
||||
if let Some(layout) = layout {
|
||||
let gutter_bounds = RectF::new(bounds.origin(), layout.gutter_size);
|
||||
@@ -438,10 +437,10 @@ impl Element for BufferElement {
|
||||
layout.text_size,
|
||||
);
|
||||
|
||||
if self.view(ctx.app).is_gutter_visible() {
|
||||
self.paint_gutter(gutter_bounds, layout, ctx);
|
||||
if self.view(cx.app).is_gutter_visible() {
|
||||
self.paint_gutter(gutter_bounds, layout, cx);
|
||||
}
|
||||
self.paint_text(text_bounds, layout, ctx);
|
||||
self.paint_text(text_bounds, layout, cx);
|
||||
|
||||
Some(PaintState {
|
||||
bounds,
|
||||
@@ -458,23 +457,23 @@ impl Element for BufferElement {
|
||||
_: RectF,
|
||||
layout: &mut Self::LayoutState,
|
||||
paint: &mut Self::PaintState,
|
||||
ctx: &mut EventContext,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
if let (Some(layout), Some(paint)) = (layout, paint) {
|
||||
match event {
|
||||
Event::LeftMouseDown { position, cmd } => {
|
||||
self.mouse_down(*position, *cmd, layout, paint, ctx)
|
||||
self.mouse_down(*position, *cmd, layout, paint, cx)
|
||||
}
|
||||
Event::LeftMouseUp { position } => self.mouse_up(*position, ctx),
|
||||
Event::LeftMouseUp { position } => self.mouse_up(*position, cx),
|
||||
Event::LeftMouseDragged { position } => {
|
||||
self.mouse_dragged(*position, layout, paint, ctx)
|
||||
self.mouse_dragged(*position, layout, paint, cx)
|
||||
}
|
||||
Event::ScrollWheel {
|
||||
position,
|
||||
delta,
|
||||
precise,
|
||||
} => self.scroll(*position, *delta, *precise, layout, paint, ctx),
|
||||
Event::KeyDown { chars, .. } => self.key_down(chars, ctx),
|
||||
} => self.scroll(*position, *delta, *precise, layout, paint, cx),
|
||||
Event::KeyDown { chars, .. } => self.key_down(chars, cx),
|
||||
_ => false,
|
||||
}
|
||||
} else {
|
||||
@@ -510,14 +509,14 @@ pub struct LayoutState {
|
||||
impl LayoutState {
|
||||
fn scroll_width(
|
||||
&self,
|
||||
view: &BufferView,
|
||||
view: &Editor,
|
||||
font_cache: &FontCache,
|
||||
layout_cache: &TextLayoutCache,
|
||||
app: &AppContext,
|
||||
cx: &AppContext,
|
||||
) -> f32 {
|
||||
let row = view.longest_row(app);
|
||||
let row = view.longest_row(cx);
|
||||
let longest_line_width = view
|
||||
.layout_line(row, font_cache, layout_cache, app)
|
||||
.layout_line(row, font_cache, layout_cache, cx)
|
||||
.unwrap()
|
||||
.width();
|
||||
longest_line_width.max(self.max_visible_line_width) + view.em_width(font_cache)
|
||||
@@ -525,16 +524,16 @@ impl LayoutState {
|
||||
|
||||
fn scroll_max(
|
||||
&self,
|
||||
view: &BufferView,
|
||||
view: &Editor,
|
||||
font_cache: &FontCache,
|
||||
layout_cache: &TextLayoutCache,
|
||||
app: &AppContext,
|
||||
cx: &AppContext,
|
||||
) -> Vector2F {
|
||||
vec2f(
|
||||
((self.scroll_width(view, font_cache, layout_cache, app) - self.text_size.x())
|
||||
((self.scroll_width(view, font_cache, layout_cache, cx) - self.text_size.x())
|
||||
/ view.em_width(font_cache))
|
||||
.max(0.0),
|
||||
view.max_point(app).row().saturating_sub(1) as f32,
|
||||
view.max_point(cx).row().saturating_sub(1) as f32,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -547,24 +546,24 @@ pub struct PaintState {
|
||||
impl PaintState {
|
||||
fn point_for_position(
|
||||
&self,
|
||||
view: &BufferView,
|
||||
view: &Editor,
|
||||
layout: &LayoutState,
|
||||
position: Vector2F,
|
||||
font_cache: &FontCache,
|
||||
app: &AppContext,
|
||||
cx: &AppContext,
|
||||
) -> DisplayPoint {
|
||||
let scroll_position = view.scroll_position();
|
||||
let position = position - self.text_bounds.origin();
|
||||
let y = position.y().max(0.0).min(layout.size.y());
|
||||
let row = ((y / view.line_height(font_cache)) + scroll_position.y()) as u32;
|
||||
let row = cmp::min(row, view.max_point(app).row());
|
||||
let row = cmp::min(row, view.max_point(cx).row());
|
||||
let line = &layout.line_layouts[(row - scroll_position.y() as u32) as usize];
|
||||
let x = position.x() + (scroll_position.x() * view.em_width(font_cache));
|
||||
|
||||
let column = if x >= 0.0 {
|
||||
line.index_for_x(x)
|
||||
.map(|ix| ix as u32)
|
||||
.unwrap_or(view.line_len(row, app))
|
||||
.unwrap_or(view.line_len(row, cx))
|
||||
} else {
|
||||
0
|
||||
};
|
||||
@@ -579,8 +578,8 @@ struct Cursor {
|
||||
}
|
||||
|
||||
impl Cursor {
|
||||
fn paint(&self, ctx: &mut PaintContext) {
|
||||
ctx.scene.push_quad(Quad {
|
||||
fn paint(&self, cx: &mut PaintContext) {
|
||||
cx.scene.push_quad(Quad {
|
||||
bounds: RectF::new(self.origin, vec2f(2.0, self.line_height)),
|
||||
background: Some(ColorU::black()),
|
||||
border: Border::new(0., ColorU::black()),
|
||||
@@ -1,36 +0,0 @@
|
||||
mod buffer;
|
||||
mod buffer_element;
|
||||
pub mod buffer_view;
|
||||
pub mod display_map;
|
||||
pub mod movement;
|
||||
|
||||
pub use buffer::*;
|
||||
pub use buffer_element::*;
|
||||
pub use buffer_view::*;
|
||||
pub use display_map::DisplayPoint;
|
||||
use display_map::*;
|
||||
use std::{
|
||||
cmp,
|
||||
ops::{Range, RangeInclusive},
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Bias {
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
trait RangeExt<T> {
|
||||
fn sorted(&self) -> Range<T>;
|
||||
fn to_inclusive(&self) -> RangeInclusive<T>;
|
||||
}
|
||||
|
||||
impl<T: Ord + Clone> RangeExt<T> for Range<T> {
|
||||
fn sorted(&self) -> Self {
|
||||
cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
|
||||
}
|
||||
|
||||
fn to_inclusive(&self) -> RangeInclusive<T> {
|
||||
self.start.clone()..=self.end.clone()
|
||||
}
|
||||
}
|
||||
+21
-21
@@ -2,34 +2,34 @@ use super::{Bias, DisplayMap, DisplayPoint, SelectionGoal};
|
||||
use anyhow::Result;
|
||||
use gpui::AppContext;
|
||||
|
||||
pub fn left(map: &DisplayMap, mut point: DisplayPoint, app: &AppContext) -> Result<DisplayPoint> {
|
||||
pub fn left(map: &DisplayMap, mut point: DisplayPoint, cx: &AppContext) -> Result<DisplayPoint> {
|
||||
if point.column() > 0 {
|
||||
*point.column_mut() -= 1;
|
||||
} else if point.row() > 0 {
|
||||
*point.row_mut() -= 1;
|
||||
*point.column_mut() = map.line_len(point.row(), app);
|
||||
*point.column_mut() = map.line_len(point.row(), cx);
|
||||
}
|
||||
Ok(map.snapshot(app).clip_point(point, Bias::Left))
|
||||
Ok(map.snapshot(cx).clip_point(point, Bias::Left))
|
||||
}
|
||||
|
||||
pub fn right(map: &DisplayMap, mut point: DisplayPoint, app: &AppContext) -> Result<DisplayPoint> {
|
||||
let max_column = map.line_len(point.row(), app);
|
||||
pub fn right(map: &DisplayMap, mut point: DisplayPoint, cx: &AppContext) -> Result<DisplayPoint> {
|
||||
let max_column = map.line_len(point.row(), cx);
|
||||
if point.column() < max_column {
|
||||
*point.column_mut() += 1;
|
||||
} else if point.row() < map.max_point(app).row() {
|
||||
} else if point.row() < map.max_point(cx).row() {
|
||||
*point.row_mut() += 1;
|
||||
*point.column_mut() = 0;
|
||||
}
|
||||
Ok(map.snapshot(app).clip_point(point, Bias::Right))
|
||||
Ok(map.snapshot(cx).clip_point(point, Bias::Right))
|
||||
}
|
||||
|
||||
pub fn up(
|
||||
map: &DisplayMap,
|
||||
mut point: DisplayPoint,
|
||||
goal: SelectionGoal,
|
||||
app: &AppContext,
|
||||
cx: &AppContext,
|
||||
) -> Result<(DisplayPoint, SelectionGoal)> {
|
||||
let map = map.snapshot(app);
|
||||
let map = map.snapshot(cx);
|
||||
let goal_column = if let SelectionGoal::Column(column) = goal {
|
||||
column
|
||||
} else {
|
||||
@@ -50,10 +50,10 @@ pub fn down(
|
||||
map: &DisplayMap,
|
||||
mut point: DisplayPoint,
|
||||
goal: SelectionGoal,
|
||||
app: &AppContext,
|
||||
cx: &AppContext,
|
||||
) -> Result<(DisplayPoint, SelectionGoal)> {
|
||||
let max_point = map.max_point(app);
|
||||
let map = map.snapshot(app);
|
||||
let max_point = map.max_point(cx);
|
||||
let map = map.snapshot(cx);
|
||||
let goal_column = if let SelectionGoal::Column(column) = goal {
|
||||
column
|
||||
} else {
|
||||
@@ -74,9 +74,9 @@ pub fn line_beginning(
|
||||
map: &DisplayMap,
|
||||
point: DisplayPoint,
|
||||
toggle_indent: bool,
|
||||
app: &AppContext,
|
||||
cx: &AppContext,
|
||||
) -> Result<DisplayPoint> {
|
||||
let (indent, is_blank) = map.line_indent(point.row(), app);
|
||||
let (indent, is_blank) = map.line_indent(point.row(), cx);
|
||||
if toggle_indent && !is_blank && point.column() != indent {
|
||||
Ok(DisplayPoint::new(point.row(), indent))
|
||||
} else {
|
||||
@@ -84,30 +84,30 @@ pub fn line_beginning(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn line_end(map: &DisplayMap, point: DisplayPoint, app: &AppContext) -> Result<DisplayPoint> {
|
||||
pub fn line_end(map: &DisplayMap, point: DisplayPoint, cx: &AppContext) -> Result<DisplayPoint> {
|
||||
Ok(DisplayPoint::new(
|
||||
point.row(),
|
||||
map.line_len(point.row(), app),
|
||||
map.line_len(point.row(), cx),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn prev_word_boundary(
|
||||
map: &DisplayMap,
|
||||
point: DisplayPoint,
|
||||
app: &AppContext,
|
||||
cx: &AppContext,
|
||||
) -> Result<DisplayPoint> {
|
||||
if point.column() == 0 {
|
||||
if point.row() == 0 {
|
||||
Ok(DisplayPoint::new(0, 0))
|
||||
} else {
|
||||
let row = point.row() - 1;
|
||||
Ok(DisplayPoint::new(row, map.line_len(row, app)))
|
||||
Ok(DisplayPoint::new(row, map.line_len(row, cx)))
|
||||
}
|
||||
} else {
|
||||
let mut boundary = DisplayPoint::new(point.row(), 0);
|
||||
let mut column = 0;
|
||||
let mut prev_c = None;
|
||||
for c in map.snapshot(app).chars_at(boundary) {
|
||||
for c in map.snapshot(cx).chars_at(boundary) {
|
||||
if column >= point.column() {
|
||||
break;
|
||||
}
|
||||
@@ -126,10 +126,10 @@ pub fn prev_word_boundary(
|
||||
pub fn next_word_boundary(
|
||||
map: &DisplayMap,
|
||||
mut point: DisplayPoint,
|
||||
app: &AppContext,
|
||||
cx: &AppContext,
|
||||
) -> Result<DisplayPoint> {
|
||||
let mut prev_c = None;
|
||||
for c in map.snapshot(app).chars_at(point) {
|
||||
for c in map.snapshot(cx).chars_at(point) {
|
||||
if prev_c.is_some() && (c == '\n' || char_kind(prev_c.unwrap()) != char_kind(c)) {
|
||||
break;
|
||||
}
|
||||
|
||||
+137
-138
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
editor::{buffer_view, BufferView},
|
||||
editor::{self, Editor},
|
||||
settings::Settings,
|
||||
util,
|
||||
workspace::Workspace,
|
||||
@@ -28,7 +28,7 @@ pub struct FileFinder {
|
||||
handle: WeakViewHandle<Self>,
|
||||
settings: watch::Receiver<Settings>,
|
||||
workspace: WeakViewHandle<Workspace>,
|
||||
query_buffer: ViewHandle<BufferView>,
|
||||
query_buffer: ViewHandle<Editor>,
|
||||
search_count: usize,
|
||||
latest_search_id: usize,
|
||||
latest_search_did_cancel: bool,
|
||||
@@ -39,15 +39,15 @@ pub struct FileFinder {
|
||||
list_state: UniformListState,
|
||||
}
|
||||
|
||||
pub fn init(app: &mut MutableAppContext) {
|
||||
app.add_action("file_finder:toggle", FileFinder::toggle);
|
||||
app.add_action("file_finder:confirm", FileFinder::confirm);
|
||||
app.add_action("file_finder:select", FileFinder::select);
|
||||
app.add_action("menu:select_prev", FileFinder::select_prev);
|
||||
app.add_action("menu:select_next", FileFinder::select_next);
|
||||
app.add_action("uniform_list:scroll", FileFinder::scroll);
|
||||
pub fn init(cx: &mut MutableAppContext) {
|
||||
cx.add_action("file_finder:toggle", FileFinder::toggle);
|
||||
cx.add_action("file_finder:confirm", FileFinder::confirm);
|
||||
cx.add_action("file_finder:select", FileFinder::select);
|
||||
cx.add_action("menu:select_prev", FileFinder::select_prev);
|
||||
cx.add_action("menu:select_next", FileFinder::select_next);
|
||||
cx.add_action("uniform_list:scroll", FileFinder::scroll);
|
||||
|
||||
app.add_bindings(vec![
|
||||
cx.add_bindings(vec![
|
||||
Binding::new("cmd-p", "file_finder:toggle", None),
|
||||
Binding::new("escape", "file_finder:toggle", Some("FileFinder")),
|
||||
Binding::new("enter", "file_finder:confirm", Some("FileFinder")),
|
||||
@@ -92,14 +92,14 @@ impl View for FileFinder {
|
||||
.named("file finder")
|
||||
}
|
||||
|
||||
fn on_focus(&mut self, ctx: &mut ViewContext<Self>) {
|
||||
ctx.focus(&self.query_buffer);
|
||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
||||
cx.focus(&self.query_buffer);
|
||||
}
|
||||
|
||||
fn keymap_context(&self, _: &AppContext) -> keymap::Context {
|
||||
let mut ctx = Self::default_keymap_context();
|
||||
ctx.set.insert("menu".into());
|
||||
ctx
|
||||
let mut cx = Self::default_keymap_context();
|
||||
cx.set.insert("menu".into());
|
||||
cx
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,13 +123,13 @@ impl FileFinder {
|
||||
let list = UniformList::new(
|
||||
self.list_state.clone(),
|
||||
self.matches.len(),
|
||||
move |mut range, items, app| {
|
||||
let finder = handle.upgrade(app).unwrap();
|
||||
let finder = finder.read(app);
|
||||
move |mut range, items, cx| {
|
||||
let finder = handle.upgrade(cx).unwrap();
|
||||
let finder = finder.read(cx);
|
||||
let start = range.start;
|
||||
range.end = cmp::min(range.end, finder.matches.len());
|
||||
items.extend(finder.matches[range].iter().enumerate().filter_map(
|
||||
move |(i, path_match)| finder.render_match(path_match, start + i, app),
|
||||
move |(i, path_match)| finder.render_match(path_match, start + i, cx),
|
||||
));
|
||||
},
|
||||
);
|
||||
@@ -145,9 +145,9 @@ impl FileFinder {
|
||||
&self,
|
||||
path_match: &PathMatch,
|
||||
index: usize,
|
||||
app: &AppContext,
|
||||
cx: &AppContext,
|
||||
) -> Option<ElementBox> {
|
||||
self.labels_for_match(path_match, app).map(
|
||||
self.labels_for_match(path_match, cx).map(
|
||||
|(file_name, file_name_positions, full_path, full_path_positions)| {
|
||||
let settings = self.settings.borrow();
|
||||
let highlight_color = ColorU::from_u32(0x304ee2ff);
|
||||
@@ -208,8 +208,8 @@ impl FileFinder {
|
||||
|
||||
let entry = (path_match.tree_id, path_match.path.clone());
|
||||
EventHandler::new(container.boxed())
|
||||
.on_mouse_down(move |ctx| {
|
||||
ctx.dispatch_action("file_finder:select", entry.clone());
|
||||
.on_mouse_down(move |cx| {
|
||||
cx.dispatch_action("file_finder:select", entry.clone());
|
||||
true
|
||||
})
|
||||
.named("match")
|
||||
@@ -220,9 +220,9 @@ impl FileFinder {
|
||||
fn labels_for_match(
|
||||
&self,
|
||||
path_match: &PathMatch,
|
||||
app: &AppContext,
|
||||
cx: &AppContext,
|
||||
) -> Option<(String, Vec<usize>, String, Vec<usize>)> {
|
||||
self.worktree(path_match.tree_id, app).map(|tree| {
|
||||
self.worktree(path_match.tree_id, cx).map(|tree| {
|
||||
let prefix = if path_match.include_root_name {
|
||||
tree.root_name()
|
||||
} else {
|
||||
@@ -254,12 +254,12 @@ impl FileFinder {
|
||||
})
|
||||
}
|
||||
|
||||
fn toggle(workspace_view: &mut Workspace, _: &(), ctx: &mut ViewContext<Workspace>) {
|
||||
workspace_view.toggle_modal(ctx, |ctx, workspace_view| {
|
||||
let workspace = ctx.handle();
|
||||
fn toggle(workspace_view: &mut Workspace, _: &(), cx: &mut ViewContext<Workspace>) {
|
||||
workspace_view.toggle_modal(cx, |cx, workspace_view| {
|
||||
let workspace = cx.handle();
|
||||
let finder =
|
||||
ctx.add_view(|ctx| Self::new(workspace_view.settings.clone(), workspace, ctx));
|
||||
ctx.subscribe_to_view(&finder, Self::on_event);
|
||||
cx.add_view(|cx| Self::new(workspace_view.settings.clone(), workspace, cx));
|
||||
cx.subscribe_to_view(&finder, Self::on_event);
|
||||
finder
|
||||
});
|
||||
}
|
||||
@@ -268,17 +268,17 @@ impl FileFinder {
|
||||
workspace_view: &mut Workspace,
|
||||
_: ViewHandle<FileFinder>,
|
||||
event: &Event,
|
||||
ctx: &mut ViewContext<Workspace>,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) {
|
||||
match event {
|
||||
Event::Selected(tree_id, path) => {
|
||||
workspace_view
|
||||
.open_entry((*tree_id, path.clone()), ctx)
|
||||
.open_entry((*tree_id, path.clone()), cx)
|
||||
.map(|d| d.detach());
|
||||
workspace_view.dismiss_modal(ctx);
|
||||
workspace_view.dismiss_modal(cx);
|
||||
}
|
||||
Event::Dismissed => {
|
||||
workspace_view.dismiss_modal(ctx);
|
||||
workspace_view.dismiss_modal(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -286,15 +286,15 @@ impl FileFinder {
|
||||
pub fn new(
|
||||
settings: watch::Receiver<Settings>,
|
||||
workspace: ViewHandle<Workspace>,
|
||||
ctx: &mut ViewContext<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
ctx.observe_view(&workspace, Self::workspace_updated);
|
||||
cx.observe_view(&workspace, Self::workspace_updated);
|
||||
|
||||
let query_buffer = ctx.add_view(|ctx| BufferView::single_line(settings.clone(), ctx));
|
||||
ctx.subscribe_to_view(&query_buffer, Self::on_query_buffer_event);
|
||||
let query_buffer = cx.add_view(|cx| Editor::single_line(settings.clone(), cx));
|
||||
cx.subscribe_to_view(&query_buffer, Self::on_query_editor_event);
|
||||
|
||||
Self {
|
||||
handle: ctx.handle().downgrade(),
|
||||
handle: cx.handle().downgrade(),
|
||||
settings,
|
||||
workspace: workspace.downgrade(),
|
||||
query_buffer,
|
||||
@@ -309,33 +309,32 @@ impl FileFinder {
|
||||
}
|
||||
}
|
||||
|
||||
fn workspace_updated(&mut self, _: ViewHandle<Workspace>, ctx: &mut ViewContext<Self>) {
|
||||
if let Some(task) = self.spawn_search(self.query_buffer.read(ctx).text(ctx.as_ref()), ctx) {
|
||||
fn workspace_updated(&mut self, _: ViewHandle<Workspace>, cx: &mut ViewContext<Self>) {
|
||||
if let Some(task) = self.spawn_search(self.query_buffer.read(cx).text(cx.as_ref()), cx) {
|
||||
task.detach();
|
||||
}
|
||||
}
|
||||
|
||||
fn on_query_buffer_event(
|
||||
fn on_query_editor_event(
|
||||
&mut self,
|
||||
_: ViewHandle<BufferView>,
|
||||
event: &buffer_view::Event,
|
||||
ctx: &mut ViewContext<Self>,
|
||||
_: ViewHandle<Editor>,
|
||||
event: &editor::Event,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
use buffer_view::Event::*;
|
||||
match event {
|
||||
Edited => {
|
||||
let query = self.query_buffer.read(ctx).text(ctx.as_ref());
|
||||
editor::Event::Edited => {
|
||||
let query = self.query_buffer.read(cx).text(cx.as_ref());
|
||||
if query.is_empty() {
|
||||
self.latest_search_id = util::post_inc(&mut self.search_count);
|
||||
self.matches.clear();
|
||||
ctx.notify();
|
||||
cx.notify();
|
||||
} else {
|
||||
if let Some(task) = self.spawn_search(query, ctx) {
|
||||
if let Some(task) = self.spawn_search(query, cx) {
|
||||
task.detach();
|
||||
}
|
||||
}
|
||||
}
|
||||
Blurred => ctx.emit(Event::Dismissed),
|
||||
editor::Event::Blurred => cx.emit(Event::Dismissed),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -353,7 +352,7 @@ impl FileFinder {
|
||||
0
|
||||
}
|
||||
|
||||
fn select_prev(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
|
||||
fn select_prev(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let mut selected_index = self.selected_index();
|
||||
if selected_index > 0 {
|
||||
selected_index -= 1;
|
||||
@@ -361,10 +360,10 @@ impl FileFinder {
|
||||
self.selected = Some((mat.tree_id, mat.path.clone()));
|
||||
}
|
||||
self.list_state.scroll_to(selected_index);
|
||||
ctx.notify();
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn select_next(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
|
||||
fn select_next(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let mut selected_index = self.selected_index();
|
||||
if selected_index + 1 < self.matches.len() {
|
||||
selected_index += 1;
|
||||
@@ -372,39 +371,39 @@ impl FileFinder {
|
||||
self.selected = Some((mat.tree_id, mat.path.clone()));
|
||||
}
|
||||
self.list_state.scroll_to(selected_index);
|
||||
ctx.notify();
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn scroll(&mut self, _: &f32, ctx: &mut ViewContext<Self>) {
|
||||
ctx.notify();
|
||||
fn scroll(&mut self, _: &f32, cx: &mut ViewContext<Self>) {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn confirm(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
|
||||
fn confirm(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
if let Some(m) = self.matches.get(self.selected_index()) {
|
||||
ctx.emit(Event::Selected(m.tree_id, m.path.clone()));
|
||||
cx.emit(Event::Selected(m.tree_id, m.path.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
fn select(&mut self, (tree_id, path): &(usize, Arc<Path>), ctx: &mut ViewContext<Self>) {
|
||||
ctx.emit(Event::Selected(*tree_id, path.clone()));
|
||||
fn select(&mut self, (tree_id, path): &(usize, Arc<Path>), cx: &mut ViewContext<Self>) {
|
||||
cx.emit(Event::Selected(*tree_id, path.clone()));
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn spawn_search(&mut self, query: String, ctx: &mut ViewContext<Self>) -> Option<Task<()>> {
|
||||
fn spawn_search(&mut self, query: String, cx: &mut ViewContext<Self>) -> Option<Task<()>> {
|
||||
let snapshots = self
|
||||
.workspace
|
||||
.upgrade(&ctx)?
|
||||
.read(ctx)
|
||||
.upgrade(&cx)?
|
||||
.read(cx)
|
||||
.worktrees()
|
||||
.iter()
|
||||
.map(|tree| tree.read(ctx).snapshot())
|
||||
.map(|tree| tree.read(cx).snapshot())
|
||||
.collect::<Vec<_>>();
|
||||
let search_id = util::post_inc(&mut self.search_count);
|
||||
let pool = ctx.as_ref().thread_pool().clone();
|
||||
let pool = cx.as_ref().thread_pool().clone();
|
||||
self.cancel_flag.store(true, atomic::Ordering::Relaxed);
|
||||
self.cancel_flag = Arc::new(AtomicBool::new(false));
|
||||
let cancel_flag = self.cancel_flag.clone();
|
||||
let background_task = ctx.background_executor().spawn(async move {
|
||||
let background_task = cx.background_executor().spawn(async move {
|
||||
let include_root_name = snapshots.len() > 1;
|
||||
let matches = match_paths(
|
||||
snapshots.iter(),
|
||||
@@ -420,16 +419,16 @@ impl FileFinder {
|
||||
(search_id, did_cancel, query, matches)
|
||||
});
|
||||
|
||||
Some(ctx.spawn(|this, mut ctx| async move {
|
||||
Some(cx.spawn(|this, mut cx| async move {
|
||||
let matches = background_task.await;
|
||||
this.update(&mut ctx, |this, ctx| this.update_matches(matches, ctx));
|
||||
this.update(&mut cx, |this, cx| this.update_matches(matches, cx));
|
||||
}))
|
||||
}
|
||||
|
||||
fn update_matches(
|
||||
&mut self,
|
||||
(search_id, did_cancel, query, matches): (usize, bool, String, Vec<PathMatch>),
|
||||
ctx: &mut ViewContext<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
if search_id >= self.latest_search_id {
|
||||
self.latest_search_id = search_id;
|
||||
@@ -441,17 +440,17 @@ impl FileFinder {
|
||||
self.latest_search_query = query;
|
||||
self.latest_search_did_cancel = did_cancel;
|
||||
self.list_state.scroll_to(self.selected_index());
|
||||
ctx.notify();
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
|
||||
fn worktree<'a>(&'a self, tree_id: usize, app: &'a AppContext) -> Option<&'a Worktree> {
|
||||
fn worktree<'a>(&'a self, tree_id: usize, cx: &'a AppContext) -> Option<&'a Worktree> {
|
||||
self.workspace
|
||||
.upgrade(app)?
|
||||
.read(app)
|
||||
.upgrade(cx)?
|
||||
.read(cx)
|
||||
.worktrees()
|
||||
.get(&tree_id)
|
||||
.map(|worktree| worktree.read(app))
|
||||
.map(|worktree| worktree.read(cx))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,75 +467,75 @@ mod tests {
|
||||
use tempdir::TempDir;
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_matching_paths(mut app: gpui::TestAppContext) {
|
||||
async fn test_matching_paths(mut cx: gpui::TestAppContext) {
|
||||
let tmp_dir = TempDir::new("example").unwrap();
|
||||
fs::create_dir(tmp_dir.path().join("a")).unwrap();
|
||||
fs::write(tmp_dir.path().join("a/banana"), "banana").unwrap();
|
||||
fs::write(tmp_dir.path().join("a/bandana"), "bandana").unwrap();
|
||||
app.update(|ctx| {
|
||||
super::init(ctx);
|
||||
editor::init(ctx);
|
||||
cx.update(|cx| {
|
||||
super::init(cx);
|
||||
editor::init(cx);
|
||||
});
|
||||
|
||||
let app_state = app.read(build_app_state);
|
||||
let (window_id, workspace) = app.add_window(|ctx| {
|
||||
let app_state = cx.read(build_app_state);
|
||||
let (window_id, workspace) = cx.add_window(|cx| {
|
||||
let mut workspace =
|
||||
Workspace::new(0, app_state.settings, app_state.language_registry, ctx);
|
||||
workspace.add_worktree(tmp_dir.path(), ctx);
|
||||
Workspace::new(0, app_state.settings, app_state.language_registry, cx);
|
||||
workspace.add_worktree(tmp_dir.path(), cx);
|
||||
workspace
|
||||
});
|
||||
app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
|
||||
cx.read(|cx| workspace.read(cx).worktree_scans_complete(cx))
|
||||
.await;
|
||||
app.dispatch_action(
|
||||
cx.dispatch_action(
|
||||
window_id,
|
||||
vec![workspace.id()],
|
||||
"file_finder:toggle".into(),
|
||||
(),
|
||||
);
|
||||
|
||||
let finder = app.read(|ctx| {
|
||||
let finder = cx.read(|cx| {
|
||||
workspace
|
||||
.read(ctx)
|
||||
.read(cx)
|
||||
.modal()
|
||||
.cloned()
|
||||
.unwrap()
|
||||
.downcast::<FileFinder>()
|
||||
.unwrap()
|
||||
});
|
||||
let query_buffer = app.read(|ctx| finder.read(ctx).query_buffer.clone());
|
||||
let query_buffer = cx.read(|cx| finder.read(cx).query_buffer.clone());
|
||||
|
||||
let chain = vec![finder.id(), query_buffer.id()];
|
||||
app.dispatch_action(window_id, chain.clone(), "buffer:insert", "b".to_string());
|
||||
app.dispatch_action(window_id, chain.clone(), "buffer:insert", "n".to_string());
|
||||
app.dispatch_action(window_id, chain.clone(), "buffer:insert", "a".to_string());
|
||||
cx.dispatch_action(window_id, chain.clone(), "buffer:insert", "b".to_string());
|
||||
cx.dispatch_action(window_id, chain.clone(), "buffer:insert", "n".to_string());
|
||||
cx.dispatch_action(window_id, chain.clone(), "buffer:insert", "a".to_string());
|
||||
finder
|
||||
.condition(&app, |finder, _| finder.matches.len() == 2)
|
||||
.condition(&cx, |finder, _| finder.matches.len() == 2)
|
||||
.await;
|
||||
|
||||
let active_pane = app.read(|ctx| workspace.read(ctx).active_pane().clone());
|
||||
app.dispatch_action(
|
||||
let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
|
||||
cx.dispatch_action(
|
||||
window_id,
|
||||
vec![workspace.id(), finder.id()],
|
||||
"menu:select_next",
|
||||
(),
|
||||
);
|
||||
app.dispatch_action(
|
||||
cx.dispatch_action(
|
||||
window_id,
|
||||
vec![workspace.id(), finder.id()],
|
||||
"file_finder:confirm",
|
||||
(),
|
||||
);
|
||||
active_pane
|
||||
.condition(&app, |pane, _| pane.active_item().is_some())
|
||||
.condition(&cx, |pane, _| pane.active_item().is_some())
|
||||
.await;
|
||||
app.read(|ctx| {
|
||||
let active_item = active_pane.read(ctx).active_item().unwrap();
|
||||
assert_eq!(active_item.title(ctx), "bandana");
|
||||
cx.read(|cx| {
|
||||
let active_item = active_pane.read(cx).active_item().unwrap();
|
||||
assert_eq!(active_item.title(cx), "bandana");
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_matching_cancellation(mut app: gpui::TestAppContext) {
|
||||
async fn test_matching_cancellation(mut cx: gpui::TestAppContext) {
|
||||
let tmp_dir = temp_tree(json!({
|
||||
"hello": "",
|
||||
"goodbye": "",
|
||||
@@ -546,35 +545,35 @@ mod tests {
|
||||
"hi": "",
|
||||
"hiccup": "",
|
||||
}));
|
||||
let app_state = app.read(build_app_state);
|
||||
let (_, workspace) = app.add_window(|ctx| {
|
||||
let app_state = cx.read(build_app_state);
|
||||
let (_, workspace) = cx.add_window(|cx| {
|
||||
let mut workspace = Workspace::new(
|
||||
0,
|
||||
app_state.settings.clone(),
|
||||
app_state.language_registry.clone(),
|
||||
ctx,
|
||||
cx,
|
||||
);
|
||||
workspace.add_worktree(tmp_dir.path(), ctx);
|
||||
workspace.add_worktree(tmp_dir.path(), cx);
|
||||
workspace
|
||||
});
|
||||
app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
|
||||
cx.read(|cx| workspace.read(cx).worktree_scans_complete(cx))
|
||||
.await;
|
||||
let (_, finder) =
|
||||
app.add_window(|ctx| FileFinder::new(app_state.settings, workspace.clone(), ctx));
|
||||
cx.add_window(|cx| FileFinder::new(app_state.settings, workspace.clone(), cx));
|
||||
|
||||
let query = "hi".to_string();
|
||||
finder
|
||||
.update(&mut app, |f, ctx| f.spawn_search(query.clone(), ctx))
|
||||
.update(&mut cx, |f, cx| f.spawn_search(query.clone(), cx))
|
||||
.unwrap()
|
||||
.await;
|
||||
finder.read_with(&app, |f, _| assert_eq!(f.matches.len(), 5));
|
||||
finder.read_with(&cx, |f, _| assert_eq!(f.matches.len(), 5));
|
||||
|
||||
finder.update(&mut app, |finder, ctx| {
|
||||
finder.update(&mut cx, |finder, cx| {
|
||||
let matches = finder.matches.clone();
|
||||
|
||||
// Simulate a search being cancelled after the time limit,
|
||||
// returning only a subset of the matches that would have been found.
|
||||
finder.spawn_search(query.clone(), ctx).unwrap().detach();
|
||||
finder.spawn_search(query.clone(), cx).unwrap().detach();
|
||||
finder.update_matches(
|
||||
(
|
||||
finder.latest_search_id,
|
||||
@@ -582,11 +581,11 @@ mod tests {
|
||||
query.clone(),
|
||||
vec![matches[1].clone(), matches[3].clone()],
|
||||
),
|
||||
ctx,
|
||||
cx,
|
||||
);
|
||||
|
||||
// Simulate another cancellation.
|
||||
finder.spawn_search(query.clone(), ctx).unwrap().detach();
|
||||
finder.spawn_search(query.clone(), cx).unwrap().detach();
|
||||
finder.update_matches(
|
||||
(
|
||||
finder.latest_search_id,
|
||||
@@ -594,7 +593,7 @@ mod tests {
|
||||
query.clone(),
|
||||
vec![matches[0].clone(), matches[2].clone(), matches[3].clone()],
|
||||
),
|
||||
ctx,
|
||||
cx,
|
||||
);
|
||||
|
||||
assert_eq!(finder.matches, matches[0..4])
|
||||
@@ -602,41 +601,41 @@ mod tests {
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_single_file_worktrees(mut app: gpui::TestAppContext) {
|
||||
async fn test_single_file_worktrees(mut cx: gpui::TestAppContext) {
|
||||
let temp_dir = TempDir::new("test-single-file-worktrees").unwrap();
|
||||
let dir_path = temp_dir.path().join("the-parent-dir");
|
||||
let file_path = dir_path.join("the-file");
|
||||
fs::create_dir(&dir_path).unwrap();
|
||||
fs::write(&file_path, "").unwrap();
|
||||
|
||||
let app_state = app.read(build_app_state);
|
||||
let (_, workspace) = app.add_window(|ctx| {
|
||||
let app_state = cx.read(build_app_state);
|
||||
let (_, workspace) = cx.add_window(|cx| {
|
||||
let mut workspace = Workspace::new(
|
||||
0,
|
||||
app_state.settings.clone(),
|
||||
app_state.language_registry.clone(),
|
||||
ctx,
|
||||
cx,
|
||||
);
|
||||
workspace.add_worktree(&file_path, ctx);
|
||||
workspace.add_worktree(&file_path, cx);
|
||||
workspace
|
||||
});
|
||||
app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
|
||||
cx.read(|cx| workspace.read(cx).worktree_scans_complete(cx))
|
||||
.await;
|
||||
let (_, finder) =
|
||||
app.add_window(|ctx| FileFinder::new(app_state.settings, workspace.clone(), ctx));
|
||||
cx.add_window(|cx| FileFinder::new(app_state.settings, workspace.clone(), cx));
|
||||
|
||||
// Even though there is only one worktree, that worktree's filename
|
||||
// is included in the matching, because the worktree is a single file.
|
||||
finder
|
||||
.update(&mut app, |f, ctx| f.spawn_search("thf".into(), ctx))
|
||||
.update(&mut cx, |f, cx| f.spawn_search("thf".into(), cx))
|
||||
.unwrap()
|
||||
.await;
|
||||
app.read(|ctx| {
|
||||
let finder = finder.read(ctx);
|
||||
cx.read(|cx| {
|
||||
let finder = finder.read(cx);
|
||||
assert_eq!(finder.matches.len(), 1);
|
||||
|
||||
let (file_name, file_name_positions, full_path, full_path_positions) =
|
||||
finder.labels_for_match(&finder.matches[0], ctx).unwrap();
|
||||
finder.labels_for_match(&finder.matches[0], cx).unwrap();
|
||||
assert_eq!(file_name, "the-file");
|
||||
assert_eq!(file_name_positions, &[0, 1, 4]);
|
||||
assert_eq!(full_path, "the-file");
|
||||
@@ -646,57 +645,57 @@ mod tests {
|
||||
// Since the worktree root is a file, searching for its name followed by a slash does
|
||||
// not match anything.
|
||||
finder
|
||||
.update(&mut app, |f, ctx| f.spawn_search("thf/".into(), ctx))
|
||||
.update(&mut cx, |f, cx| f.spawn_search("thf/".into(), cx))
|
||||
.unwrap()
|
||||
.await;
|
||||
finder.read_with(&app, |f, _| assert_eq!(f.matches.len(), 0));
|
||||
finder.read_with(&cx, |f, _| assert_eq!(f.matches.len(), 0));
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_multiple_matches_with_same_relative_path(mut app: gpui::TestAppContext) {
|
||||
async fn test_multiple_matches_with_same_relative_path(mut cx: gpui::TestAppContext) {
|
||||
let tmp_dir = temp_tree(json!({
|
||||
"dir1": { "a.txt": "" },
|
||||
"dir2": { "a.txt": "" }
|
||||
}));
|
||||
|
||||
let app_state = app.read(build_app_state);
|
||||
let app_state = cx.read(build_app_state);
|
||||
|
||||
let (_, workspace) = app.add_window(|ctx| {
|
||||
let (_, workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(
|
||||
0,
|
||||
app_state.settings.clone(),
|
||||
app_state.language_registry.clone(),
|
||||
ctx,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
||||
workspace
|
||||
.update(&mut app, |workspace, ctx| {
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
workspace.open_paths(
|
||||
&[tmp_dir.path().join("dir1"), tmp_dir.path().join("dir2")],
|
||||
ctx,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await;
|
||||
app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
|
||||
cx.read(|cx| workspace.read(cx).worktree_scans_complete(cx))
|
||||
.await;
|
||||
|
||||
let (_, finder) =
|
||||
app.add_window(|ctx| FileFinder::new(app_state.settings, workspace.clone(), ctx));
|
||||
cx.add_window(|cx| FileFinder::new(app_state.settings, workspace.clone(), cx));
|
||||
|
||||
// Run a search that matches two files with the same relative path.
|
||||
finder
|
||||
.update(&mut app, |f, ctx| f.spawn_search("a.t".into(), ctx))
|
||||
.update(&mut cx, |f, cx| f.spawn_search("a.t".into(), cx))
|
||||
.unwrap()
|
||||
.await;
|
||||
|
||||
// Can switch between different matches with the same relative path.
|
||||
finder.update(&mut app, |f, ctx| {
|
||||
finder.update(&mut cx, |f, cx| {
|
||||
assert_eq!(f.matches.len(), 2);
|
||||
assert_eq!(f.selected_index(), 0);
|
||||
f.select_next(&(), ctx);
|
||||
f.select_next(&(), cx);
|
||||
assert_eq!(f.selected_index(), 1);
|
||||
f.select_prev(&(), ctx);
|
||||
f.select_prev(&(), cx);
|
||||
assert_eq!(f.selected_index(), 0);
|
||||
});
|
||||
}
|
||||
|
||||
+7
-7
@@ -24,19 +24,19 @@ fn main() {
|
||||
settings,
|
||||
};
|
||||
|
||||
app.run(move |ctx| {
|
||||
ctx.set_menus(menus::menus(app_state.settings.clone()));
|
||||
workspace::init(ctx);
|
||||
editor::init(ctx);
|
||||
file_finder::init(ctx);
|
||||
app.run(move |cx| {
|
||||
cx.set_menus(menus::menus(app_state.settings.clone()));
|
||||
workspace::init(cx);
|
||||
editor::init(cx);
|
||||
file_finder::init(cx);
|
||||
|
||||
if stdout_is_a_pty() {
|
||||
ctx.platform().activate(true);
|
||||
cx.platform().activate(true);
|
||||
}
|
||||
|
||||
let paths = collect_path_args();
|
||||
if !paths.is_empty() {
|
||||
ctx.dispatch_global_action(
|
||||
cx.dispatch_global_action(
|
||||
"workspace:open_paths",
|
||||
OpenParams {
|
||||
paths,
|
||||
|
||||
@@ -25,7 +25,7 @@ pub trait KeyedItem: Item {
|
||||
pub trait Summary: Default + Clone + fmt::Debug {
|
||||
type Context;
|
||||
|
||||
fn add_summary(&mut self, summary: &Self, ctx: &Self::Context);
|
||||
fn add_summary(&mut self, summary: &Self, cx: &Self::Context);
|
||||
}
|
||||
|
||||
pub trait Dimension<'a, S: Summary>: Clone + fmt::Debug + Default {
|
||||
@@ -37,7 +37,7 @@ impl<'a, T: Summary> Dimension<'a, T> for () {
|
||||
}
|
||||
|
||||
pub trait SeekDimension<'a, T: Summary>: Dimension<'a, T> {
|
||||
fn cmp(&self, other: &Self, ctx: &T::Context) -> Ordering;
|
||||
fn cmp(&self, other: &Self, cx: &T::Context) -> Ordering;
|
||||
}
|
||||
|
||||
impl<'a, S: Summary, T: Dimension<'a, S> + Ord> SeekDimension<'a, S> for T {
|
||||
@@ -64,9 +64,9 @@ impl<T: Item> SumTree<T> {
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn from_item(item: T, ctx: &<T::Summary as Summary>::Context) -> Self {
|
||||
pub fn from_item(item: T, cx: &<T::Summary as Summary>::Context) -> Self {
|
||||
let mut tree = Self::new();
|
||||
tree.push(item, ctx);
|
||||
tree.push(item, cx);
|
||||
tree
|
||||
}
|
||||
|
||||
@@ -101,14 +101,14 @@ impl<T: Item> SumTree<T> {
|
||||
self.rightmost_leaf().0.items().last()
|
||||
}
|
||||
|
||||
pub fn update_last(&mut self, f: impl FnOnce(&mut T), ctx: &<T::Summary as Summary>::Context) {
|
||||
self.update_last_recursive(f, ctx);
|
||||
pub fn update_last(&mut self, f: impl FnOnce(&mut T), cx: &<T::Summary as Summary>::Context) {
|
||||
self.update_last_recursive(f, cx);
|
||||
}
|
||||
|
||||
fn update_last_recursive(
|
||||
&mut self,
|
||||
f: impl FnOnce(&mut T),
|
||||
ctx: &<T::Summary as Summary>::Context,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) -> Option<T::Summary> {
|
||||
match Arc::make_mut(&mut self.0) {
|
||||
Node::Internal {
|
||||
@@ -119,8 +119,8 @@ impl<T: Item> SumTree<T> {
|
||||
} => {
|
||||
let last_summary = child_summaries.last_mut().unwrap();
|
||||
let last_child = child_trees.last_mut().unwrap();
|
||||
*last_summary = last_child.update_last_recursive(f, ctx).unwrap();
|
||||
*summary = sum(child_summaries.iter(), ctx);
|
||||
*last_summary = last_child.update_last_recursive(f, cx).unwrap();
|
||||
*summary = sum(child_summaries.iter(), cx);
|
||||
Some(summary.clone())
|
||||
}
|
||||
Node::Leaf {
|
||||
@@ -132,7 +132,7 @@ impl<T: Item> SumTree<T> {
|
||||
{
|
||||
(f)(item);
|
||||
*item_summary = item.summary();
|
||||
*summary = sum(item_summaries.iter(), ctx);
|
||||
*summary = sum(item_summaries.iter(), cx);
|
||||
Some(summary.clone())
|
||||
} else {
|
||||
None
|
||||
@@ -165,7 +165,7 @@ impl<T: Item> SumTree<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extend<I>(&mut self, iter: I, ctx: &<T::Summary as Summary>::Context)
|
||||
pub fn extend<I>(&mut self, iter: I, cx: &<T::Summary as Summary>::Context)
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
{
|
||||
@@ -173,7 +173,7 @@ impl<T: Item> SumTree<T> {
|
||||
|
||||
for item in iter {
|
||||
if leaf.is_some() && leaf.as_ref().unwrap().items().len() == 2 * TREE_BASE {
|
||||
self.push_tree(SumTree(Arc::new(leaf.take().unwrap())), ctx);
|
||||
self.push_tree(SumTree(Arc::new(leaf.take().unwrap())), cx);
|
||||
}
|
||||
|
||||
if leaf.is_none() {
|
||||
@@ -191,7 +191,7 @@ impl<T: Item> SumTree<T> {
|
||||
}) = leaf.as_mut()
|
||||
{
|
||||
let item_summary = item.summary();
|
||||
summary.add_summary(&item_summary, ctx);
|
||||
summary.add_summary(&item_summary, cx);
|
||||
items.push(item);
|
||||
item_summaries.push(item_summary);
|
||||
} else {
|
||||
@@ -200,11 +200,11 @@ impl<T: Item> SumTree<T> {
|
||||
}
|
||||
|
||||
if leaf.is_some() {
|
||||
self.push_tree(SumTree(Arc::new(leaf.take().unwrap())), ctx);
|
||||
self.push_tree(SumTree(Arc::new(leaf.take().unwrap())), cx);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(&mut self, item: T, ctx: &<T::Summary as Summary>::Context) {
|
||||
pub fn push(&mut self, item: T, cx: &<T::Summary as Summary>::Context) {
|
||||
let summary = item.summary();
|
||||
self.push_tree(
|
||||
SumTree(Arc::new(Node::Leaf {
|
||||
@@ -212,18 +212,18 @@ impl<T: Item> SumTree<T> {
|
||||
items: ArrayVec::from_iter(Some(item)),
|
||||
item_summaries: ArrayVec::from_iter(Some(summary)),
|
||||
})),
|
||||
ctx,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn push_tree(&mut self, other: Self, ctx: &<T::Summary as Summary>::Context) {
|
||||
pub fn push_tree(&mut self, other: Self, cx: &<T::Summary as Summary>::Context) {
|
||||
if !other.0.is_leaf() || other.0.items().len() > 0 {
|
||||
if self.0.height() < other.0.height() {
|
||||
for tree in other.0.child_trees() {
|
||||
self.push_tree(tree.clone(), ctx);
|
||||
self.push_tree(tree.clone(), cx);
|
||||
}
|
||||
} else if let Some(split_tree) = self.push_tree_recursive(other, ctx) {
|
||||
*self = Self::from_child_trees(self.clone(), split_tree, ctx);
|
||||
} else if let Some(split_tree) = self.push_tree_recursive(other, cx) {
|
||||
*self = Self::from_child_trees(self.clone(), split_tree, cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -231,7 +231,7 @@ impl<T: Item> SumTree<T> {
|
||||
fn push_tree_recursive(
|
||||
&mut self,
|
||||
other: SumTree<T>,
|
||||
ctx: &<T::Summary as Summary>::Context,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) -> Option<SumTree<T>> {
|
||||
match Arc::make_mut(&mut self.0) {
|
||||
Node::Internal {
|
||||
@@ -242,7 +242,7 @@ impl<T: Item> SumTree<T> {
|
||||
..
|
||||
} => {
|
||||
let other_node = other.0.clone();
|
||||
summary.add_summary(other_node.summary(), ctx);
|
||||
summary.add_summary(other_node.summary(), cx);
|
||||
|
||||
let height_delta = *height - other_node.height();
|
||||
let mut summaries_to_append = ArrayVec::<[T::Summary; 2 * TREE_BASE]>::new();
|
||||
@@ -257,7 +257,7 @@ impl<T: Item> SumTree<T> {
|
||||
let tree_to_append = child_trees
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.push_tree_recursive(other, ctx);
|
||||
.push_tree_recursive(other, cx);
|
||||
*child_summaries.last_mut().unwrap() =
|
||||
child_trees.last().unwrap().0.summary().clone();
|
||||
|
||||
@@ -287,13 +287,13 @@ impl<T: Item> SumTree<T> {
|
||||
left_trees = all_trees.by_ref().take(midpoint).collect();
|
||||
right_trees = all_trees.collect();
|
||||
}
|
||||
*summary = sum(left_summaries.iter(), ctx);
|
||||
*summary = sum(left_summaries.iter(), cx);
|
||||
*child_summaries = left_summaries;
|
||||
*child_trees = left_trees;
|
||||
|
||||
Some(SumTree(Arc::new(Node::Internal {
|
||||
height: *height,
|
||||
summary: sum(right_summaries.iter(), ctx),
|
||||
summary: sum(right_summaries.iter(), cx),
|
||||
child_summaries: right_summaries,
|
||||
child_trees: right_trees,
|
||||
})))
|
||||
@@ -332,14 +332,14 @@ impl<T: Item> SumTree<T> {
|
||||
}
|
||||
*items = left_items;
|
||||
*item_summaries = left_summaries;
|
||||
*summary = sum(item_summaries.iter(), ctx);
|
||||
*summary = sum(item_summaries.iter(), cx);
|
||||
Some(SumTree(Arc::new(Node::Leaf {
|
||||
items: right_items,
|
||||
summary: sum(right_summaries.iter(), ctx),
|
||||
summary: sum(right_summaries.iter(), cx),
|
||||
item_summaries: right_summaries,
|
||||
})))
|
||||
} else {
|
||||
summary.add_summary(other_node.summary(), ctx);
|
||||
summary.add_summary(other_node.summary(), cx);
|
||||
items.extend(other_node.items().iter().cloned());
|
||||
item_summaries.extend(other_node.child_summaries().iter().cloned());
|
||||
None
|
||||
@@ -351,7 +351,7 @@ impl<T: Item> SumTree<T> {
|
||||
fn from_child_trees(
|
||||
left: SumTree<T>,
|
||||
right: SumTree<T>,
|
||||
ctx: &<T::Summary as Summary>::Context,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) -> Self {
|
||||
let height = left.0.height() + 1;
|
||||
let mut child_summaries = ArrayVec::new();
|
||||
@@ -362,7 +362,7 @@ impl<T: Item> SumTree<T> {
|
||||
child_trees.push(right);
|
||||
SumTree(Arc::new(Node::Internal {
|
||||
height,
|
||||
summary: sum(child_summaries.iter(), ctx),
|
||||
summary: sum(child_summaries.iter(), cx),
|
||||
child_summaries,
|
||||
child_trees,
|
||||
}))
|
||||
@@ -389,12 +389,12 @@ impl<T: Item> SumTree<T> {
|
||||
|
||||
impl<T: KeyedItem> SumTree<T> {
|
||||
#[allow(unused)]
|
||||
pub fn insert(&mut self, item: T, ctx: &<T::Summary as Summary>::Context) {
|
||||
pub fn insert(&mut self, item: T, cx: &<T::Summary as Summary>::Context) {
|
||||
*self = {
|
||||
let mut cursor = self.cursor::<T::Key, ()>();
|
||||
let mut new_tree = cursor.slice(&item.key(), SeekBias::Left, ctx);
|
||||
new_tree.push(item, ctx);
|
||||
new_tree.push_tree(cursor.suffix(ctx), ctx);
|
||||
let mut new_tree = cursor.slice(&item.key(), SeekBias::Left, cx);
|
||||
new_tree.push(item, cx);
|
||||
new_tree.push_tree(cursor.suffix(cx), cx);
|
||||
new_tree
|
||||
};
|
||||
}
|
||||
@@ -402,7 +402,7 @@ impl<T: KeyedItem> SumTree<T> {
|
||||
pub fn edit(
|
||||
&mut self,
|
||||
mut edits: Vec<Edit<T>>,
|
||||
ctx: &<T::Summary as Summary>::Context,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) -> Vec<T> {
|
||||
if edits.is_empty() {
|
||||
return Vec::new();
|
||||
@@ -416,7 +416,7 @@ impl<T: KeyedItem> SumTree<T> {
|
||||
let mut new_tree = SumTree::new();
|
||||
let mut buffered_items = Vec::new();
|
||||
|
||||
cursor.seek(&T::Key::default(), SeekBias::Left, ctx);
|
||||
cursor.seek(&T::Key::default(), SeekBias::Left, cx);
|
||||
for edit in edits {
|
||||
let new_key = edit.key();
|
||||
let mut old_item = cursor.item();
|
||||
@@ -425,9 +425,9 @@ impl<T: KeyedItem> SumTree<T> {
|
||||
.as_ref()
|
||||
.map_or(false, |old_item| old_item.key() < new_key)
|
||||
{
|
||||
new_tree.extend(buffered_items.drain(..), ctx);
|
||||
let slice = cursor.slice(&new_key, SeekBias::Left, ctx);
|
||||
new_tree.push_tree(slice, ctx);
|
||||
new_tree.extend(buffered_items.drain(..), cx);
|
||||
let slice = cursor.slice(&new_key, SeekBias::Left, cx);
|
||||
new_tree.push_tree(slice, cx);
|
||||
old_item = cursor.item();
|
||||
}
|
||||
|
||||
@@ -446,17 +446,17 @@ impl<T: KeyedItem> SumTree<T> {
|
||||
}
|
||||
}
|
||||
|
||||
new_tree.extend(buffered_items, ctx);
|
||||
new_tree.push_tree(cursor.suffix(ctx), ctx);
|
||||
new_tree.extend(buffered_items, cx);
|
||||
new_tree.push_tree(cursor.suffix(cx), cx);
|
||||
new_tree
|
||||
};
|
||||
|
||||
removed
|
||||
}
|
||||
|
||||
pub fn get(&self, key: &T::Key, ctx: &<T::Summary as Summary>::Context) -> Option<&T> {
|
||||
pub fn get(&self, key: &T::Key, cx: &<T::Summary as Summary>::Context) -> Option<&T> {
|
||||
let mut cursor = self.cursor::<T::Key, ()>();
|
||||
if cursor.seek(key, SeekBias::Left, ctx) {
|
||||
if cursor.seek(key, SeekBias::Left, cx) {
|
||||
cursor.item()
|
||||
} else {
|
||||
None
|
||||
@@ -553,14 +553,14 @@ impl<T: KeyedItem> Edit<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn sum<'a, T, I>(iter: I, ctx: &T::Context) -> T
|
||||
fn sum<'a, T, I>(iter: I, cx: &T::Context) -> T
|
||||
where
|
||||
T: 'a + Summary,
|
||||
I: Iterator<Item = &'a T>,
|
||||
{
|
||||
let mut sum = T::default();
|
||||
for value in iter {
|
||||
sum.add_summary(value, ctx);
|
||||
sum.add_summary(value, cx);
|
||||
}
|
||||
sum
|
||||
}
|
||||
+25
-30
@@ -342,33 +342,28 @@ where
|
||||
S: SeekDimension<'a, T::Summary>,
|
||||
U: Dimension<'a, T::Summary>,
|
||||
{
|
||||
pub fn seek(
|
||||
&mut self,
|
||||
pos: &S,
|
||||
bias: SeekBias,
|
||||
ctx: &<T::Summary as Summary>::Context,
|
||||
) -> bool {
|
||||
pub fn seek(&mut self, pos: &S, bias: SeekBias, cx: &<T::Summary as Summary>::Context) -> bool {
|
||||
self.reset();
|
||||
self.seek_internal::<()>(pos, bias, &mut SeekAggregate::None, ctx)
|
||||
self.seek_internal::<()>(pos, bias, &mut SeekAggregate::None, cx)
|
||||
}
|
||||
|
||||
pub fn seek_forward(
|
||||
&mut self,
|
||||
pos: &S,
|
||||
bias: SeekBias,
|
||||
ctx: &<T::Summary as Summary>::Context,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) -> bool {
|
||||
self.seek_internal::<()>(pos, bias, &mut SeekAggregate::None, ctx)
|
||||
self.seek_internal::<()>(pos, bias, &mut SeekAggregate::None, cx)
|
||||
}
|
||||
|
||||
pub fn slice(
|
||||
&mut self,
|
||||
end: &S,
|
||||
bias: SeekBias,
|
||||
ctx: &<T::Summary as Summary>::Context,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) -> SumTree<T> {
|
||||
let mut slice = SeekAggregate::Slice(SumTree::new());
|
||||
self.seek_internal::<()>(end, bias, &mut slice, ctx);
|
||||
self.seek_internal::<()>(end, bias, &mut slice, cx);
|
||||
if let SeekAggregate::Slice(slice) = slice {
|
||||
slice
|
||||
} else {
|
||||
@@ -376,10 +371,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn suffix(&mut self, ctx: &<T::Summary as Summary>::Context) -> SumTree<T> {
|
||||
pub fn suffix(&mut self, cx: &<T::Summary as Summary>::Context) -> SumTree<T> {
|
||||
let extent = self.tree.extent::<S>();
|
||||
let mut slice = SeekAggregate::Slice(SumTree::new());
|
||||
self.seek_internal::<()>(&extent, SeekBias::Right, &mut slice, ctx);
|
||||
self.seek_internal::<()>(&extent, SeekBias::Right, &mut slice, cx);
|
||||
if let SeekAggregate::Slice(slice) = slice {
|
||||
slice
|
||||
} else {
|
||||
@@ -391,13 +386,13 @@ where
|
||||
&mut self,
|
||||
end: &S,
|
||||
bias: SeekBias,
|
||||
ctx: &<T::Summary as Summary>::Context,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) -> D
|
||||
where
|
||||
D: Dimension<'a, T::Summary>,
|
||||
{
|
||||
let mut summary = SeekAggregate::Summary(D::default());
|
||||
self.seek_internal(end, bias, &mut summary, ctx);
|
||||
self.seek_internal(end, bias, &mut summary, cx);
|
||||
if let SeekAggregate::Summary(summary) = summary {
|
||||
summary
|
||||
} else {
|
||||
@@ -410,12 +405,12 @@ where
|
||||
target: &S,
|
||||
bias: SeekBias,
|
||||
aggregate: &mut SeekAggregate<T, D>,
|
||||
ctx: &<T::Summary as Summary>::Context,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) -> bool
|
||||
where
|
||||
D: Dimension<'a, T::Summary>,
|
||||
{
|
||||
debug_assert!(target.cmp(&self.seek_dimension, ctx) >= Ordering::Equal);
|
||||
debug_assert!(target.cmp(&self.seek_dimension, cx) >= Ordering::Equal);
|
||||
let mut containing_subtree = None;
|
||||
|
||||
if self.did_seek {
|
||||
@@ -435,7 +430,7 @@ where
|
||||
let mut child_end = self.seek_dimension.clone();
|
||||
child_end.add_summary(&child_summary);
|
||||
|
||||
let comparison = target.cmp(&child_end, ctx);
|
||||
let comparison = target.cmp(&child_end, cx);
|
||||
if comparison == Ordering::Greater
|
||||
|| (comparison == Ordering::Equal && bias == SeekBias::Right)
|
||||
{
|
||||
@@ -444,7 +439,7 @@ where
|
||||
match aggregate {
|
||||
SeekAggregate::None => {}
|
||||
SeekAggregate::Slice(slice) => {
|
||||
slice.push_tree(child_tree.clone(), ctx);
|
||||
slice.push_tree(child_tree.clone(), cx);
|
||||
}
|
||||
SeekAggregate::Summary(summary) => {
|
||||
summary.add_summary(child_summary);
|
||||
@@ -477,7 +472,7 @@ where
|
||||
let mut item_end = self.seek_dimension.clone();
|
||||
item_end.add_summary(item_summary);
|
||||
|
||||
let comparison = target.cmp(&item_end, ctx);
|
||||
let comparison = target.cmp(&item_end, cx);
|
||||
if comparison == Ordering::Greater
|
||||
|| (comparison == Ordering::Equal && bias == SeekBias::Right)
|
||||
{
|
||||
@@ -491,7 +486,7 @@ where
|
||||
slice_items_summary
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.add_summary(item_summary, ctx);
|
||||
.add_summary(item_summary, cx);
|
||||
}
|
||||
SeekAggregate::Summary(summary) => {
|
||||
summary.add_summary(item_summary);
|
||||
@@ -506,7 +501,7 @@ where
|
||||
items: slice_items,
|
||||
item_summaries: slice_item_summaries,
|
||||
})),
|
||||
ctx,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
break 'outer;
|
||||
@@ -521,7 +516,7 @@ where
|
||||
items: slice_items,
|
||||
item_summaries: slice_item_summaries,
|
||||
})),
|
||||
ctx,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -551,7 +546,7 @@ where
|
||||
let mut child_end = self.seek_dimension.clone();
|
||||
child_end.add_summary(child_summary);
|
||||
|
||||
let comparison = target.cmp(&child_end, ctx);
|
||||
let comparison = target.cmp(&child_end, cx);
|
||||
if comparison == Ordering::Greater
|
||||
|| (comparison == Ordering::Equal && bias == SeekBias::Right)
|
||||
{
|
||||
@@ -560,7 +555,7 @@ where
|
||||
match aggregate {
|
||||
SeekAggregate::None => {}
|
||||
SeekAggregate::Slice(slice) => {
|
||||
slice.push_tree(child_trees[index].clone(), ctx);
|
||||
slice.push_tree(child_trees[index].clone(), cx);
|
||||
}
|
||||
SeekAggregate::Summary(summary) => {
|
||||
summary.add_summary(child_summary);
|
||||
@@ -597,7 +592,7 @@ where
|
||||
let mut child_end = self.seek_dimension.clone();
|
||||
child_end.add_summary(item_summary);
|
||||
|
||||
let comparison = target.cmp(&child_end, ctx);
|
||||
let comparison = target.cmp(&child_end, cx);
|
||||
if comparison == Ordering::Greater
|
||||
|| (comparison == Ordering::Equal && bias == SeekBias::Right)
|
||||
{
|
||||
@@ -610,7 +605,7 @@ where
|
||||
slice_items_summary
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.add_summary(item_summary, ctx);
|
||||
.add_summary(item_summary, cx);
|
||||
slice_item_summaries.push(item_summary.clone());
|
||||
}
|
||||
SeekAggregate::Summary(summary) => {
|
||||
@@ -636,7 +631,7 @@ where
|
||||
items: slice_items,
|
||||
item_summaries: slice_item_summaries,
|
||||
})),
|
||||
ctx,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -658,9 +653,9 @@ where
|
||||
if let Some(summary) = self.item_summary() {
|
||||
end.add_summary(summary);
|
||||
}
|
||||
target.cmp(&end, ctx) == Ordering::Equal
|
||||
target.cmp(&end, cx) == Ordering::Equal
|
||||
} else {
|
||||
target.cmp(&self.seek_dimension, ctx) == Ordering::Equal
|
||||
target.cmp(&self.seek_dimension, cx) == Ordering::Equal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -144,8 +144,8 @@ fn write_tree(path: &Path, tree: serde_json::Value) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_app_state(ctx: &AppContext) -> AppState {
|
||||
let settings = settings::channel(&ctx.font_cache()).unwrap().1;
|
||||
pub fn build_app_state(cx: &AppContext) -> AppState {
|
||||
let settings = settings::channel(&cx.font_cache()).unwrap().1;
|
||||
let language_registry = Arc::new(LanguageRegistry::new());
|
||||
AppState {
|
||||
settings,
|
||||
|
||||
+324
-328
File diff suppressed because it is too large
Load Diff
+66
-87
@@ -10,42 +10,39 @@ use gpui::{
|
||||
use postage::watch;
|
||||
use std::{cmp, path::Path, sync::Arc};
|
||||
|
||||
pub fn init(app: &mut MutableAppContext) {
|
||||
app.add_action(
|
||||
pub fn init(cx: &mut MutableAppContext) {
|
||||
cx.add_action(
|
||||
"pane:activate_item",
|
||||
|pane: &mut Pane, index: &usize, ctx| {
|
||||
pane.activate_item(*index, ctx);
|
||||
|pane: &mut Pane, index: &usize, cx| {
|
||||
pane.activate_item(*index, cx);
|
||||
},
|
||||
);
|
||||
app.add_action("pane:activate_prev_item", |pane: &mut Pane, _: &(), ctx| {
|
||||
pane.activate_prev_item(ctx);
|
||||
cx.add_action("pane:activate_prev_item", |pane: &mut Pane, _: &(), cx| {
|
||||
pane.activate_prev_item(cx);
|
||||
});
|
||||
app.add_action("pane:activate_next_item", |pane: &mut Pane, _: &(), ctx| {
|
||||
pane.activate_next_item(ctx);
|
||||
cx.add_action("pane:activate_next_item", |pane: &mut Pane, _: &(), cx| {
|
||||
pane.activate_next_item(cx);
|
||||
});
|
||||
app.add_action("pane:close_active_item", |pane: &mut Pane, _: &(), ctx| {
|
||||
pane.close_active_item(ctx);
|
||||
cx.add_action("pane:close_active_item", |pane: &mut Pane, _: &(), cx| {
|
||||
pane.close_active_item(cx);
|
||||
});
|
||||
app.add_action(
|
||||
"pane:close_item",
|
||||
|pane: &mut Pane, item_id: &usize, ctx| {
|
||||
pane.close_item(*item_id, ctx);
|
||||
},
|
||||
);
|
||||
app.add_action("pane:split_up", |pane: &mut Pane, _: &(), ctx| {
|
||||
pane.split(SplitDirection::Up, ctx);
|
||||
cx.add_action("pane:close_item", |pane: &mut Pane, item_id: &usize, cx| {
|
||||
pane.close_item(*item_id, cx);
|
||||
});
|
||||
app.add_action("pane:split_down", |pane: &mut Pane, _: &(), ctx| {
|
||||
pane.split(SplitDirection::Down, ctx);
|
||||
cx.add_action("pane:split_up", |pane: &mut Pane, _: &(), cx| {
|
||||
pane.split(SplitDirection::Up, cx);
|
||||
});
|
||||
app.add_action("pane:split_left", |pane: &mut Pane, _: &(), ctx| {
|
||||
pane.split(SplitDirection::Left, ctx);
|
||||
cx.add_action("pane:split_down", |pane: &mut Pane, _: &(), cx| {
|
||||
pane.split(SplitDirection::Down, cx);
|
||||
});
|
||||
app.add_action("pane:split_right", |pane: &mut Pane, _: &(), ctx| {
|
||||
pane.split(SplitDirection::Right, ctx);
|
||||
cx.add_action("pane:split_left", |pane: &mut Pane, _: &(), cx| {
|
||||
pane.split(SplitDirection::Left, cx);
|
||||
});
|
||||
cx.add_action("pane:split_right", |pane: &mut Pane, _: &(), cx| {
|
||||
pane.split(SplitDirection::Right, cx);
|
||||
});
|
||||
|
||||
app.add_bindings(vec![
|
||||
cx.add_bindings(vec![
|
||||
Binding::new("shift-cmd-{", "pane:activate_prev_item", Some("Pane")),
|
||||
Binding::new("shift-cmd-}", "pane:activate_next_item", Some("Pane")),
|
||||
Binding::new("cmd-w", "pane:close_active_item", Some("Pane")),
|
||||
@@ -88,18 +85,14 @@ impl Pane {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn activate(&self, ctx: &mut ViewContext<Self>) {
|
||||
ctx.emit(Event::Activate);
|
||||
pub fn activate(&self, cx: &mut ViewContext<Self>) {
|
||||
cx.emit(Event::Activate);
|
||||
}
|
||||
|
||||
pub fn add_item(
|
||||
&mut self,
|
||||
item: Box<dyn ItemViewHandle>,
|
||||
ctx: &mut ViewContext<Self>,
|
||||
) -> usize {
|
||||
pub fn add_item(&mut self, item: Box<dyn ItemViewHandle>, cx: &mut ViewContext<Self>) -> usize {
|
||||
let item_idx = cmp::min(self.active_item + 1, self.items.len());
|
||||
self.items.insert(item_idx, item);
|
||||
ctx.notify();
|
||||
cx.notify();
|
||||
item_idx
|
||||
}
|
||||
|
||||
@@ -115,13 +108,13 @@ impl Pane {
|
||||
pub fn activate_entry(
|
||||
&mut self,
|
||||
entry_id: (usize, Arc<Path>),
|
||||
ctx: &mut ViewContext<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> bool {
|
||||
if let Some(index) = self.items.iter().position(|item| {
|
||||
item.entry_id(ctx.as_ref())
|
||||
item.entry_id(cx.as_ref())
|
||||
.map_or(false, |id| id == entry_id)
|
||||
}) {
|
||||
self.activate_item(index, ctx);
|
||||
self.activate_item(index, cx);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@@ -132,64 +125,64 @@ impl Pane {
|
||||
self.items.iter().position(|i| i.id() == item.id())
|
||||
}
|
||||
|
||||
pub fn activate_item(&mut self, index: usize, ctx: &mut ViewContext<Self>) {
|
||||
pub fn activate_item(&mut self, index: usize, cx: &mut ViewContext<Self>) {
|
||||
if index < self.items.len() {
|
||||
self.active_item = index;
|
||||
self.focus_active_item(ctx);
|
||||
ctx.notify();
|
||||
self.focus_active_item(cx);
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn activate_prev_item(&mut self, ctx: &mut ViewContext<Self>) {
|
||||
pub fn activate_prev_item(&mut self, cx: &mut ViewContext<Self>) {
|
||||
if self.active_item > 0 {
|
||||
self.active_item -= 1;
|
||||
} else if self.items.len() > 0 {
|
||||
self.active_item = self.items.len() - 1;
|
||||
}
|
||||
self.focus_active_item(ctx);
|
||||
ctx.notify();
|
||||
self.focus_active_item(cx);
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn activate_next_item(&mut self, ctx: &mut ViewContext<Self>) {
|
||||
pub fn activate_next_item(&mut self, cx: &mut ViewContext<Self>) {
|
||||
if self.active_item + 1 < self.items.len() {
|
||||
self.active_item += 1;
|
||||
} else {
|
||||
self.active_item = 0;
|
||||
}
|
||||
self.focus_active_item(ctx);
|
||||
ctx.notify();
|
||||
self.focus_active_item(cx);
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn close_active_item(&mut self, ctx: &mut ViewContext<Self>) {
|
||||
pub fn close_active_item(&mut self, cx: &mut ViewContext<Self>) {
|
||||
if !self.items.is_empty() {
|
||||
self.close_item(self.items[self.active_item].id(), ctx)
|
||||
self.close_item(self.items[self.active_item].id(), cx)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close_item(&mut self, item_id: usize, ctx: &mut ViewContext<Self>) {
|
||||
pub fn close_item(&mut self, item_id: usize, cx: &mut ViewContext<Self>) {
|
||||
self.items.retain(|item| item.id() != item_id);
|
||||
self.active_item = cmp::min(self.active_item, self.items.len().saturating_sub(1));
|
||||
if self.items.is_empty() {
|
||||
ctx.emit(Event::Remove);
|
||||
cx.emit(Event::Remove);
|
||||
}
|
||||
ctx.notify();
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn focus_active_item(&mut self, ctx: &mut ViewContext<Self>) {
|
||||
fn focus_active_item(&mut self, cx: &mut ViewContext<Self>) {
|
||||
if let Some(active_item) = self.active_item() {
|
||||
ctx.focus(active_item.to_any());
|
||||
cx.focus(active_item.to_any());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn split(&mut self, direction: SplitDirection, ctx: &mut ViewContext<Self>) {
|
||||
ctx.emit(Event::Split(direction));
|
||||
pub fn split(&mut self, direction: SplitDirection, cx: &mut ViewContext<Self>) {
|
||||
cx.emit(Event::Split(direction));
|
||||
}
|
||||
|
||||
fn render_tabs(&self, ctx: &AppContext) -> ElementBox {
|
||||
fn render_tabs(&self, cx: &AppContext) -> ElementBox {
|
||||
let settings = self.settings.borrow();
|
||||
let border_color = ColorU::from_u32(0xdbdbdcff);
|
||||
let line_height = ctx.font_cache().line_height(
|
||||
ctx.font_cache().default_font(settings.ui_font_family),
|
||||
let line_height = cx.font_cache().line_height(
|
||||
cx.font_cache().default_font(settings.ui_font_family),
|
||||
settings.ui_font_size,
|
||||
);
|
||||
|
||||
@@ -201,8 +194,8 @@ impl Pane {
|
||||
row.add_child(
|
||||
Expanded::new(
|
||||
1.0,
|
||||
MouseEventHandler::new::<Tab, _>(item.id(), ctx, |mouse_state| {
|
||||
let title = item.title(ctx);
|
||||
MouseEventHandler::new::<Tab, _>(item.id(), cx, |mouse_state| {
|
||||
let title = item.title(cx);
|
||||
|
||||
let mut border = Border::new(1.0, border_color);
|
||||
border.left = ix > 0;
|
||||
@@ -227,9 +220,9 @@ impl Pane {
|
||||
item.id(),
|
||||
line_height - 2.,
|
||||
mouse_state.hovered,
|
||||
item.is_dirty(ctx),
|
||||
item.has_conflict(ctx),
|
||||
ctx,
|
||||
item.is_dirty(cx),
|
||||
item.has_conflict(cx),
|
||||
cx,
|
||||
))
|
||||
.right()
|
||||
.boxed(),
|
||||
@@ -250,8 +243,8 @@ impl Pane {
|
||||
|
||||
ConstrainedBox::new(
|
||||
EventHandler::new(container.boxed())
|
||||
.on_mouse_down(move |ctx| {
|
||||
ctx.dispatch_action("pane:activate_item", ix);
|
||||
.on_mouse_down(move |cx| {
|
||||
cx.dispatch_action("pane:activate_item", ix);
|
||||
true
|
||||
})
|
||||
.boxed(),
|
||||
@@ -299,7 +292,7 @@ impl Pane {
|
||||
tab_hovered: bool,
|
||||
is_dirty: bool,
|
||||
has_conflict: bool,
|
||||
ctx: &AppContext,
|
||||
cx: &AppContext,
|
||||
) -> ElementBox {
|
||||
enum TabCloseButton {}
|
||||
|
||||
@@ -319,7 +312,7 @@ impl Pane {
|
||||
let icon = if tab_hovered {
|
||||
let mut icon = Svg::new("icons/x.svg");
|
||||
|
||||
MouseEventHandler::new::<TabCloseButton, _>(item_id, ctx, |mouse_state| {
|
||||
MouseEventHandler::new::<TabCloseButton, _>(item_id, cx, |mouse_state| {
|
||||
if mouse_state.hovered {
|
||||
Container::new(icon.with_color(ColorU::white()).boxed())
|
||||
.with_background_color(if mouse_state.clicked {
|
||||
@@ -336,15 +329,15 @@ impl Pane {
|
||||
icon.boxed()
|
||||
}
|
||||
})
|
||||
.on_click(move |ctx| ctx.dispatch_action("pane:close_item", item_id))
|
||||
.on_click(move |cx| cx.dispatch_action("pane:close_item", item_id))
|
||||
.named("close-tab-icon")
|
||||
} else {
|
||||
let diameter = 8.;
|
||||
ConstrainedBox::new(
|
||||
Canvas::new(move |bounds, ctx| {
|
||||
Canvas::new(move |bounds, cx| {
|
||||
if let Some(current_color) = current_color {
|
||||
let square = RectF::new(bounds.origin(), vec2f(diameter, diameter));
|
||||
ctx.scene.push_quad(Quad {
|
||||
cx.scene.push_quad(Quad {
|
||||
bounds: square,
|
||||
background: Some(current_color),
|
||||
border: Default::default(),
|
||||
@@ -374,10 +367,10 @@ impl View for Pane {
|
||||
"Pane"
|
||||
}
|
||||
|
||||
fn render<'a>(&self, app: &AppContext) -> ElementBox {
|
||||
fn render<'a>(&self, cx: &AppContext) -> ElementBox {
|
||||
if let Some(active_item) = self.active_item() {
|
||||
Flex::column()
|
||||
.with_child(self.render_tabs(app))
|
||||
.with_child(self.render_tabs(cx))
|
||||
.with_child(Expanded::new(1.0, ChildView::new(active_item.id()).boxed()).boxed())
|
||||
.named("pane")
|
||||
} else {
|
||||
@@ -385,21 +378,7 @@ impl View for Pane {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_focus(&mut self, ctx: &mut ViewContext<Self>) {
|
||||
self.focus_active_item(ctx);
|
||||
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
||||
self.focus_active_item(cx);
|
||||
}
|
||||
|
||||
// fn state(&self, app: &AppContext) -> Self::State {
|
||||
// State {
|
||||
// tabs: self
|
||||
// .items
|
||||
// .iter()
|
||||
// .enumerate()
|
||||
// .map(|(idx, item)| TabState {
|
||||
// title: item.title(app),
|
||||
// active: idx == self.active_item,
|
||||
// })
|
||||
// .collect(),
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
+87
-90
@@ -67,10 +67,10 @@ struct FileHandleState {
|
||||
}
|
||||
|
||||
impl Worktree {
|
||||
pub fn new(path: impl Into<Arc<Path>>, ctx: &mut ModelContext<Self>) -> Self {
|
||||
pub fn new(path: impl Into<Arc<Path>>, cx: &mut ModelContext<Self>) -> Self {
|
||||
let abs_path = path.into();
|
||||
let (scan_state_tx, scan_state_rx) = smol::channel::unbounded();
|
||||
let id = ctx.model_id();
|
||||
let id = cx.model_id();
|
||||
let snapshot = Snapshot {
|
||||
id,
|
||||
scan_id: 0,
|
||||
@@ -99,14 +99,13 @@ impl Worktree {
|
||||
scanner.run(event_stream)
|
||||
});
|
||||
|
||||
ctx.spawn(|this, mut ctx| {
|
||||
cx.spawn(|this, mut cx| {
|
||||
let this = this.downgrade();
|
||||
async move {
|
||||
while let Ok(scan_state) = scan_state_rx.recv().await {
|
||||
let alive = ctx.update(|ctx| {
|
||||
if let Some(handle) = this.upgrade(&ctx) {
|
||||
handle
|
||||
.update(ctx, |this, ctx| this.observe_scan_state(scan_state, ctx));
|
||||
let alive = cx.update(|cx| {
|
||||
if let Some(handle) = this.upgrade(&cx) {
|
||||
handle.update(cx, |this, cx| this.observe_scan_state(scan_state, cx));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@@ -134,21 +133,21 @@ impl Worktree {
|
||||
}
|
||||
}
|
||||
|
||||
fn observe_scan_state(&mut self, scan_state: ScanState, ctx: &mut ModelContext<Self>) {
|
||||
fn observe_scan_state(&mut self, scan_state: ScanState, cx: &mut ModelContext<Self>) {
|
||||
let _ = self.scan_state.0.blocking_send(scan_state);
|
||||
self.poll_entries(ctx);
|
||||
self.poll_entries(cx);
|
||||
}
|
||||
|
||||
fn poll_entries(&mut self, ctx: &mut ModelContext<Self>) {
|
||||
fn poll_entries(&mut self, cx: &mut ModelContext<Self>) {
|
||||
self.snapshot = self.background_snapshot.lock().clone();
|
||||
ctx.notify();
|
||||
cx.notify();
|
||||
|
||||
if self.is_scanning() && !self.poll_scheduled {
|
||||
ctx.spawn(|this, mut ctx| async move {
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
smol::Timer::after(Duration::from_millis(100)).await;
|
||||
this.update(&mut ctx, |this, ctx| {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.poll_scheduled = false;
|
||||
this.poll_entries(ctx);
|
||||
this.poll_entries(cx);
|
||||
})
|
||||
})
|
||||
.detach();
|
||||
@@ -187,11 +186,11 @@ impl Worktree {
|
||||
pub fn load_history(
|
||||
&self,
|
||||
path: &Path,
|
||||
ctx: &AppContext,
|
||||
cx: &AppContext,
|
||||
) -> impl Future<Output = Result<History>> {
|
||||
let path = path.to_path_buf();
|
||||
let abs_path = self.absolutize(&path);
|
||||
ctx.background_executor().spawn(async move {
|
||||
cx.background_executor().spawn(async move {
|
||||
let mut file = fs::File::open(&abs_path)?;
|
||||
let mut base_text = String::new();
|
||||
file.read_to_string(&mut base_text)?;
|
||||
@@ -199,11 +198,11 @@ impl Worktree {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn save<'a>(&self, path: &Path, content: Rope, ctx: &AppContext) -> Task<Result<()>> {
|
||||
pub fn save<'a>(&self, path: &Path, content: Rope, cx: &AppContext) -> Task<Result<()>> {
|
||||
let handles = self.handles.clone();
|
||||
let path = path.to_path_buf();
|
||||
let abs_path = self.absolutize(&path);
|
||||
ctx.background_executor().spawn(async move {
|
||||
cx.background_executor().spawn(async move {
|
||||
let buffer_size = content.summary().bytes.min(10 * 1024);
|
||||
let file = fs::File::create(&abs_path)?;
|
||||
let mut writer = io::BufWriter::with_capacity(buffer_size, &file);
|
||||
@@ -430,12 +429,12 @@ impl FileHandle {
|
||||
|
||||
/// Returns the last component of this handle's absolute path. If this handle refers to the root
|
||||
/// of its worktree, then this method will return the name of the worktree itself.
|
||||
pub fn file_name<'a>(&'a self, ctx: &'a AppContext) -> Option<OsString> {
|
||||
pub fn file_name<'a>(&'a self, cx: &'a AppContext) -> Option<OsString> {
|
||||
self.state
|
||||
.lock()
|
||||
.path
|
||||
.file_name()
|
||||
.or_else(|| self.worktree.read(ctx).abs_path().file_name())
|
||||
.or_else(|| self.worktree.read(cx).abs_path().file_name())
|
||||
.map(Into::into)
|
||||
}
|
||||
|
||||
@@ -451,13 +450,13 @@ impl FileHandle {
|
||||
!self.is_deleted()
|
||||
}
|
||||
|
||||
pub fn load_history(&self, ctx: &AppContext) -> impl Future<Output = Result<History>> {
|
||||
self.worktree.read(ctx).load_history(&self.path(), ctx)
|
||||
pub fn load_history(&self, cx: &AppContext) -> impl Future<Output = Result<History>> {
|
||||
self.worktree.read(cx).load_history(&self.path(), cx)
|
||||
}
|
||||
|
||||
pub fn save<'a>(&self, content: Rope, ctx: &AppContext) -> Task<Result<()>> {
|
||||
let worktree = self.worktree.read(ctx);
|
||||
worktree.save(&self.path(), content, ctx)
|
||||
pub fn save<'a>(&self, content: Rope, cx: &AppContext) -> Task<Result<()>> {
|
||||
let worktree = self.worktree.read(cx);
|
||||
worktree.save(&self.path(), content, cx)
|
||||
}
|
||||
|
||||
pub fn worktree_id(&self) -> usize {
|
||||
@@ -470,12 +469,12 @@ impl FileHandle {
|
||||
|
||||
pub fn observe_from_model<T: Entity>(
|
||||
&self,
|
||||
ctx: &mut ModelContext<T>,
|
||||
cx: &mut ModelContext<T>,
|
||||
mut callback: impl FnMut(&mut T, FileHandle, &mut ModelContext<T>) + 'static,
|
||||
) {
|
||||
let mut prev_state = self.state.lock().clone();
|
||||
let cur_state = Arc::downgrade(&self.state);
|
||||
ctx.observe(&self.worktree, move |observer, worktree, ctx| {
|
||||
cx.observe(&self.worktree, move |observer, worktree, cx| {
|
||||
if let Some(cur_state) = cur_state.upgrade() {
|
||||
let cur_state_unlocked = cur_state.lock();
|
||||
if *cur_state_unlocked != prev_state {
|
||||
@@ -487,7 +486,7 @@ impl FileHandle {
|
||||
worktree,
|
||||
state: cur_state,
|
||||
},
|
||||
ctx,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1201,23 +1200,23 @@ struct UpdateIgnoreStatusJob {
|
||||
}
|
||||
|
||||
pub trait WorktreeHandle {
|
||||
fn file(&self, path: impl AsRef<Path>, app: &mut MutableAppContext) -> Task<FileHandle>;
|
||||
fn file(&self, path: impl AsRef<Path>, cx: &mut MutableAppContext) -> Task<FileHandle>;
|
||||
|
||||
#[cfg(test)]
|
||||
fn flush_fs_events<'a>(
|
||||
&self,
|
||||
app: &'a gpui::TestAppContext,
|
||||
cx: &'a gpui::TestAppContext,
|
||||
) -> futures_core::future::LocalBoxFuture<'a, ()>;
|
||||
}
|
||||
|
||||
impl WorktreeHandle for ModelHandle<Worktree> {
|
||||
fn file(&self, path: impl AsRef<Path>, app: &mut MutableAppContext) -> Task<FileHandle> {
|
||||
fn file(&self, path: impl AsRef<Path>, cx: &mut MutableAppContext) -> Task<FileHandle> {
|
||||
let path = Arc::from(path.as_ref());
|
||||
let handle = self.clone();
|
||||
let tree = self.read(app);
|
||||
let tree = self.read(cx);
|
||||
let abs_path = tree.absolutize(&path);
|
||||
app.spawn(|ctx| async move {
|
||||
let mtime = ctx
|
||||
cx.spawn(|cx| async move {
|
||||
let mtime = cx
|
||||
.background_executor()
|
||||
.spawn(async move {
|
||||
if let Ok(metadata) = fs::metadata(&abs_path) {
|
||||
@@ -1227,7 +1226,7 @@ impl WorktreeHandle for ModelHandle<Worktree> {
|
||||
}
|
||||
})
|
||||
.await;
|
||||
let state = handle.read_with(&ctx, |tree, _| {
|
||||
let state = handle.read_with(&cx, |tree, _| {
|
||||
let mut handles = tree.handles.lock();
|
||||
if let Some(state) = handles.get(&path).and_then(Weak::upgrade) {
|
||||
state
|
||||
@@ -1267,23 +1266,23 @@ impl WorktreeHandle for ModelHandle<Worktree> {
|
||||
#[cfg(test)]
|
||||
fn flush_fs_events<'a>(
|
||||
&self,
|
||||
app: &'a gpui::TestAppContext,
|
||||
cx: &'a gpui::TestAppContext,
|
||||
) -> futures_core::future::LocalBoxFuture<'a, ()> {
|
||||
use smol::future::FutureExt;
|
||||
|
||||
let filename = "fs-event-sentinel";
|
||||
let root_path = app.read(|ctx| self.read(ctx).abs_path.clone());
|
||||
let root_path = cx.read(|cx| self.read(cx).abs_path.clone());
|
||||
let tree = self.clone();
|
||||
async move {
|
||||
fs::write(root_path.join(filename), "").unwrap();
|
||||
tree.condition(&app, |tree, _| tree.entry_for_path(filename).is_some())
|
||||
tree.condition(&cx, |tree, _| tree.entry_for_path(filename).is_some())
|
||||
.await;
|
||||
|
||||
fs::remove_file(root_path.join(filename)).unwrap();
|
||||
tree.condition(&app, |tree, _| tree.entry_for_path(filename).is_none())
|
||||
tree.condition(&cx, |tree, _| tree.entry_for_path(filename).is_none())
|
||||
.await;
|
||||
|
||||
app.read(|ctx| tree.read(ctx).scan_complete()).await;
|
||||
cx.read(|cx| tree.read(cx).scan_complete()).await;
|
||||
}
|
||||
.boxed_local()
|
||||
}
|
||||
@@ -1408,7 +1407,7 @@ mod tests {
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_populate_and_search(mut app: gpui::TestAppContext) {
|
||||
async fn test_populate_and_search(mut cx: gpui::TestAppContext) {
|
||||
let dir = temp_tree(json!({
|
||||
"root": {
|
||||
"apple": "",
|
||||
@@ -1432,11 +1431,11 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let tree = app.add_model(|ctx| Worktree::new(root_link_path, ctx));
|
||||
let tree = cx.add_model(|cx| Worktree::new(root_link_path, cx));
|
||||
|
||||
app.read(|ctx| tree.read(ctx).scan_complete()).await;
|
||||
app.read(|ctx| {
|
||||
let tree = tree.read(ctx);
|
||||
cx.read(|cx| tree.read(cx).scan_complete()).await;
|
||||
cx.read(|cx| {
|
||||
let tree = tree.read(cx);
|
||||
assert_eq!(tree.file_count(), 5);
|
||||
|
||||
assert_eq!(
|
||||
@@ -1452,7 +1451,7 @@ mod tests {
|
||||
false,
|
||||
10,
|
||||
Default::default(),
|
||||
ctx.thread_pool().clone(),
|
||||
cx.thread_pool().clone(),
|
||||
)
|
||||
.into_iter()
|
||||
.map(|result| result.path)
|
||||
@@ -1468,60 +1467,58 @@ mod tests {
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_save_file(mut app: gpui::TestAppContext) {
|
||||
async fn test_save_file(mut cx: gpui::TestAppContext) {
|
||||
let dir = temp_tree(json!({
|
||||
"file1": "the old contents",
|
||||
}));
|
||||
|
||||
let tree = app.add_model(|ctx| Worktree::new(dir.path(), ctx));
|
||||
app.read(|ctx| tree.read(ctx).scan_complete()).await;
|
||||
app.read(|ctx| assert_eq!(tree.read(ctx).file_count(), 1));
|
||||
let tree = cx.add_model(|cx| Worktree::new(dir.path(), cx));
|
||||
cx.read(|cx| tree.read(cx).scan_complete()).await;
|
||||
cx.read(|cx| assert_eq!(tree.read(cx).file_count(), 1));
|
||||
|
||||
let buffer =
|
||||
app.add_model(|ctx| Buffer::new(1, "a line of text.\n".repeat(10 * 1024), ctx));
|
||||
let buffer = cx.add_model(|cx| Buffer::new(1, "a line of text.\n".repeat(10 * 1024), cx));
|
||||
|
||||
let path = tree.update(&mut app, |tree, ctx| {
|
||||
let path = tree.update(&mut cx, |tree, cx| {
|
||||
let path = tree.files(0).next().unwrap().path().clone();
|
||||
assert_eq!(path.file_name().unwrap(), "file1");
|
||||
smol::block_on(tree.save(&path, buffer.read(ctx).snapshot().text(), ctx.as_ref()))
|
||||
smol::block_on(tree.save(&path, buffer.read(cx).snapshot().text(), cx.as_ref()))
|
||||
.unwrap();
|
||||
path
|
||||
});
|
||||
|
||||
let history = app
|
||||
.read(|ctx| tree.read(ctx).load_history(&path, ctx))
|
||||
let history = cx
|
||||
.read(|cx| tree.read(cx).load_history(&path, cx))
|
||||
.await
|
||||
.unwrap();
|
||||
app.read(|ctx| {
|
||||
assert_eq!(history.base_text.as_ref(), buffer.read(ctx).text());
|
||||
cx.read(|cx| {
|
||||
assert_eq!(history.base_text.as_ref(), buffer.read(cx).text());
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_save_in_single_file_worktree(mut app: gpui::TestAppContext) {
|
||||
async fn test_save_in_single_file_worktree(mut cx: gpui::TestAppContext) {
|
||||
let dir = temp_tree(json!({
|
||||
"file1": "the old contents",
|
||||
}));
|
||||
|
||||
let tree = app.add_model(|ctx| Worktree::new(dir.path().join("file1"), ctx));
|
||||
app.read(|ctx| tree.read(ctx).scan_complete()).await;
|
||||
app.read(|ctx| assert_eq!(tree.read(ctx).file_count(), 1));
|
||||
let tree = cx.add_model(|cx| Worktree::new(dir.path().join("file1"), cx));
|
||||
cx.read(|cx| tree.read(cx).scan_complete()).await;
|
||||
cx.read(|cx| assert_eq!(tree.read(cx).file_count(), 1));
|
||||
|
||||
let buffer =
|
||||
app.add_model(|ctx| Buffer::new(1, "a line of text.\n".repeat(10 * 1024), ctx));
|
||||
let buffer = cx.add_model(|cx| Buffer::new(1, "a line of text.\n".repeat(10 * 1024), cx));
|
||||
|
||||
let file = app.update(|ctx| tree.file("", ctx)).await;
|
||||
app.update(|ctx| {
|
||||
let file = cx.update(|cx| tree.file("", cx)).await;
|
||||
cx.update(|cx| {
|
||||
assert_eq!(file.path().file_name(), None);
|
||||
smol::block_on(file.save(buffer.read(ctx).snapshot().text(), ctx.as_ref())).unwrap();
|
||||
smol::block_on(file.save(buffer.read(cx).snapshot().text(), cx.as_ref())).unwrap();
|
||||
});
|
||||
|
||||
let history = app.read(|ctx| file.load_history(ctx)).await.unwrap();
|
||||
app.read(|ctx| assert_eq!(history.base_text.as_ref(), buffer.read(ctx).text()));
|
||||
let history = cx.read(|cx| file.load_history(cx)).await.unwrap();
|
||||
cx.read(|cx| assert_eq!(history.base_text.as_ref(), buffer.read(cx).text()));
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_rescan_simple(mut app: gpui::TestAppContext) {
|
||||
async fn test_rescan_simple(mut cx: gpui::TestAppContext) {
|
||||
let dir = temp_tree(json!({
|
||||
"a": {
|
||||
"file1": "",
|
||||
@@ -1536,31 +1533,31 @@ mod tests {
|
||||
}
|
||||
}));
|
||||
|
||||
let tree = app.add_model(|ctx| Worktree::new(dir.path(), ctx));
|
||||
let file2 = app.update(|ctx| tree.file("a/file2", ctx)).await;
|
||||
let file3 = app.update(|ctx| tree.file("a/file3", ctx)).await;
|
||||
let file4 = app.update(|ctx| tree.file("b/c/file4", ctx)).await;
|
||||
let file5 = app.update(|ctx| tree.file("b/c/file5", ctx)).await;
|
||||
let non_existent_file = app.update(|ctx| tree.file("a/file_x", ctx)).await;
|
||||
let tree = cx.add_model(|cx| Worktree::new(dir.path(), cx));
|
||||
let file2 = cx.update(|cx| tree.file("a/file2", cx)).await;
|
||||
let file3 = cx.update(|cx| tree.file("a/file3", cx)).await;
|
||||
let file4 = cx.update(|cx| tree.file("b/c/file4", cx)).await;
|
||||
let file5 = cx.update(|cx| tree.file("b/c/file5", cx)).await;
|
||||
let non_existent_file = cx.update(|cx| tree.file("a/file_x", cx)).await;
|
||||
|
||||
// After scanning, the worktree knows which files exist and which don't.
|
||||
app.read(|ctx| tree.read(ctx).scan_complete()).await;
|
||||
cx.read(|cx| tree.read(cx).scan_complete()).await;
|
||||
assert!(!file2.is_deleted());
|
||||
assert!(!file3.is_deleted());
|
||||
assert!(!file4.is_deleted());
|
||||
assert!(!file5.is_deleted());
|
||||
assert!(non_existent_file.is_deleted());
|
||||
|
||||
tree.flush_fs_events(&app).await;
|
||||
tree.flush_fs_events(&cx).await;
|
||||
std::fs::rename(dir.path().join("a/file3"), dir.path().join("b/c/file3")).unwrap();
|
||||
std::fs::remove_file(dir.path().join("b/c/file5")).unwrap();
|
||||
std::fs::rename(dir.path().join("b/c"), dir.path().join("d")).unwrap();
|
||||
std::fs::rename(dir.path().join("a/file2"), dir.path().join("a/file2.new")).unwrap();
|
||||
tree.flush_fs_events(&app).await;
|
||||
tree.flush_fs_events(&cx).await;
|
||||
|
||||
app.read(|ctx| {
|
||||
cx.read(|cx| {
|
||||
assert_eq!(
|
||||
tree.read(ctx)
|
||||
tree.read(cx)
|
||||
.paths()
|
||||
.map(|p| p.to_str().unwrap())
|
||||
.collect::<Vec<_>>(),
|
||||
@@ -1591,7 +1588,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_rescan_with_gitignore(mut app: gpui::TestAppContext) {
|
||||
async fn test_rescan_with_gitignore(mut cx: gpui::TestAppContext) {
|
||||
let dir = temp_tree(json!({
|
||||
".git": {},
|
||||
".gitignore": "ignored-dir\n",
|
||||
@@ -1603,11 +1600,11 @@ mod tests {
|
||||
}
|
||||
}));
|
||||
|
||||
let tree = app.add_model(|ctx| Worktree::new(dir.path(), ctx));
|
||||
app.read(|ctx| tree.read(ctx).scan_complete()).await;
|
||||
tree.flush_fs_events(&app).await;
|
||||
app.read(|ctx| {
|
||||
let tree = tree.read(ctx);
|
||||
let tree = cx.add_model(|cx| Worktree::new(dir.path(), cx));
|
||||
cx.read(|cx| tree.read(cx).scan_complete()).await;
|
||||
tree.flush_fs_events(&cx).await;
|
||||
cx.read(|cx| {
|
||||
let tree = tree.read(cx);
|
||||
let tracked = tree.entry_for_path("tracked-dir/tracked-file1").unwrap();
|
||||
let ignored = tree.entry_for_path("ignored-dir/ignored-file1").unwrap();
|
||||
assert_eq!(tracked.is_ignored(), false);
|
||||
@@ -1616,9 +1613,9 @@ mod tests {
|
||||
|
||||
fs::write(dir.path().join("tracked-dir/tracked-file2"), "").unwrap();
|
||||
fs::write(dir.path().join("ignored-dir/ignored-file2"), "").unwrap();
|
||||
tree.flush_fs_events(&app).await;
|
||||
app.read(|ctx| {
|
||||
let tree = tree.read(ctx);
|
||||
tree.flush_fs_events(&cx).await;
|
||||
cx.read(|cx| {
|
||||
let tree = tree.read(cx);
|
||||
let dot_git = tree.entry_for_path(".git").unwrap();
|
||||
let tracked = tree.entry_for_path("tracked-dir/tracked-file2").unwrap();
|
||||
let ignored = tree.entry_for_path("ignored-dir/ignored-file2").unwrap();
|
||||
|
||||
Reference in New Issue
Block a user