Merge remote-tracking branch 'origin/main' into jk

This commit is contained in:
Conrad Irwin 2024-01-21 22:03:24 -07:00
commit b9c7bafc80
28 changed files with 1573 additions and 1394 deletions

View file

@ -1584,27 +1584,34 @@ mod tests {
} }
fn editor_blocks(editor: &View<Editor>, cx: &mut WindowContext) -> Vec<(u32, SharedString)> { fn editor_blocks(editor: &View<Editor>, cx: &mut WindowContext) -> Vec<(u32, SharedString)> {
let editor_view = editor.clone();
editor.update(cx, |editor, cx| { editor.update(cx, |editor, cx| {
let snapshot = editor.snapshot(cx); let snapshot = editor.snapshot(cx);
snapshot snapshot
.blocks_in_range(0..snapshot.max_point().row()) .blocks_in_range(0..snapshot.max_point().row())
.enumerate() .enumerate()
.filter_map(|(ix, (row, block))| { .filter_map(|(ix, (row, block))| {
let name = match block { let name: SharedString = match block {
TransformBlock::Custom(block) => block TransformBlock::Custom(block) => cx.with_element_context({
.render(&mut BlockContext { let editor_view = editor_view.clone();
view_context: cx, |cx| -> Option<SharedString> {
anchor_x: px(0.), block
gutter_padding: px(0.), .render(&mut BlockContext {
gutter_width: px(0.), context: cx,
line_height: px(0.), anchor_x: px(0.),
em_width: px(0.), gutter_padding: px(0.),
block_id: ix, gutter_width: px(0.),
editor_style: &editor::EditorStyle::default(), line_height: px(0.),
}) em_width: px(0.),
.inner_id()? block_id: ix,
.try_into() view: editor_view,
.ok()?, editor_style: &editor::EditorStyle::default(),
})
.inner_id()?
.try_into()
.ok()
}
})?,
TransformBlock::ExcerptHeader { TransformBlock::ExcerptHeader {
starts_new_buffer, .. starts_new_buffer, ..

View file

@ -4,7 +4,7 @@ use super::{
}; };
use crate::{Anchor, Editor, EditorStyle, ExcerptId, ExcerptRange, ToPoint as _}; use crate::{Anchor, Editor, EditorStyle, ExcerptId, ExcerptRange, ToPoint as _};
use collections::{Bound, HashMap, HashSet}; use collections::{Bound, HashMap, HashSet};
use gpui::{AnyElement, Pixels, ViewContext}; use gpui::{AnyElement, ElementContext, Pixels, View};
use language::{BufferSnapshot, Chunk, Patch, Point}; use language::{BufferSnapshot, Chunk, Patch, Point};
use parking_lot::Mutex; use parking_lot::Mutex;
use std::{ use std::{
@ -81,7 +81,8 @@ pub enum BlockStyle {
} }
pub struct BlockContext<'a, 'b> { pub struct BlockContext<'a, 'b> {
pub view_context: &'b mut ViewContext<'a, Editor>, pub context: &'b mut ElementContext<'a>,
pub view: View<Editor>,
pub anchor_x: Pixels, pub anchor_x: Pixels,
pub gutter_width: Pixels, pub gutter_width: Pixels,
pub gutter_padding: Pixels, pub gutter_padding: Pixels,
@ -933,16 +934,16 @@ impl BlockDisposition {
} }
impl<'a> Deref for BlockContext<'a, '_> { impl<'a> Deref for BlockContext<'a, '_> {
type Target = ViewContext<'a, Editor>; type Target = ElementContext<'a>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
self.view_context self.context
} }
} }
impl DerefMut for BlockContext<'_, '_> { impl DerefMut for BlockContext<'_, '_> {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
self.view_context self.context
} }
} }

View file

@ -3912,7 +3912,7 @@ impl Editor {
gutter_hovered: bool, gutter_hovered: bool,
_line_height: Pixels, _line_height: Pixels,
_gutter_margin: Pixels, _gutter_margin: Pixels,
cx: &mut ViewContext<Self>, editor_view: View<Editor>,
) -> Vec<Option<IconButton>> { ) -> Vec<Option<IconButton>> {
fold_data fold_data
.iter() .iter()
@ -3922,14 +3922,19 @@ impl Editor {
.map(|(fold_status, buffer_row, active)| { .map(|(fold_status, buffer_row, active)| {
(active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| { (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
IconButton::new(ix as usize, ui::IconName::ChevronDown) IconButton::new(ix as usize, ui::IconName::ChevronDown)
.on_click(cx.listener(move |editor, _e, cx| match fold_status { .on_click({
FoldStatus::Folded => { let view = editor_view.clone();
editor.unfold_at(&UnfoldAt { buffer_row }, cx); move |_e, cx| {
view.update(cx, |editor, cx| match fold_status {
FoldStatus::Folded => {
editor.unfold_at(&UnfoldAt { buffer_row }, cx);
}
FoldStatus::Foldable => {
editor.fold_at(&FoldAt { buffer_row }, cx);
}
})
} }
FoldStatus::Foldable => { })
editor.fold_at(&FoldAt { buffer_row }, cx);
}
}))
.icon_color(ui::Color::Muted) .icon_color(ui::Color::Muted)
.icon_size(ui::IconSize::Small) .icon_size(ui::IconSize::Small)
.selected(fold_status == FoldStatus::Folded) .selected(fold_status == FoldStatus::Folded)
@ -9575,10 +9580,10 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, _is_valid: bool) -> Ren
.size(ButtonSize::Compact) .size(ButtonSize::Compact)
.style(ButtonStyle::Transparent) .style(ButtonStyle::Transparent)
.visible_on_hover(group_id) .visible_on_hover(group_id)
.on_click(cx.listener({ .on_click({
let message = diagnostic.message.clone(); let message = diagnostic.message.clone();
move |_, _, cx| cx.write_to_clipboard(ClipboardItem::new(message.clone())) move |_click, cx| cx.write_to_clipboard(ClipboardItem::new(message.clone()))
})) })
.tooltip(|cx| Tooltip::text("Copy diagnostic message", cx)), .tooltip(|cx| Tooltip::text("Copy diagnostic message", cx)),
) )
.into_any_element() .into_any_element()

View file

@ -25,12 +25,12 @@ use collections::{BTreeMap, HashMap};
use git::diff::DiffHunkStatus; use git::diff::DiffHunkStatus;
use gpui::{ use gpui::{
div, fill, outline, overlay, point, px, quad, relative, size, transparent_black, Action, div, fill, outline, overlay, point, px, quad, relative, size, transparent_black, Action,
AnchorCorner, AnyElement, AvailableSpace, BorrowWindow, Bounds, ContentMask, Corners, AnchorCorner, AnyElement, AvailableSpace, Bounds, ContentMask, Corners, CursorStyle,
CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler, Entity, Hsla, DispatchPhase, Edges, Element, ElementInputHandler, Entity, Hsla, InteractiveBounds,
InteractiveBounds, InteractiveElement, IntoElement, ModifiersChangedEvent, MouseButton, InteractiveElement, IntoElement, ModifiersChangedEvent, MouseButton, MouseDownEvent,
MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, ScrollDelta, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, ScrollDelta, ScrollWheelEvent, ShapedLine,
ScrollWheelEvent, ShapedLine, SharedString, Size, StackingOrder, StatefulInteractiveElement, SharedString, Size, StackingOrder, StatefulInteractiveElement, Style, Styled, TextRun,
Style, Styled, TextRun, TextStyle, View, ViewContext, WindowContext, TextStyle, View, ViewContext, WindowContext,
}; };
use itertools::Itertools; use itertools::Itertools;
use language::language_settings::ShowWhitespaceSetting; use language::language_settings::ShowWhitespaceSetting;
@ -330,7 +330,7 @@ impl EditorElement {
register_action(view, cx, Editor::display_cursor_names); register_action(view, cx, Editor::display_cursor_names);
} }
fn register_key_listeners(&self, cx: &mut WindowContext) { fn register_key_listeners(&self, cx: &mut ElementContext) {
cx.on_key_event({ cx.on_key_event({
let editor = self.editor.clone(); let editor = self.editor.clone();
move |event: &ModifiersChangedEvent, phase, cx| { move |event: &ModifiersChangedEvent, phase, cx| {
@ -628,7 +628,7 @@ impl EditorElement {
gutter_bounds: Bounds<Pixels>, gutter_bounds: Bounds<Pixels>,
text_bounds: Bounds<Pixels>, text_bounds: Bounds<Pixels>,
layout: &LayoutState, layout: &LayoutState,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
let bounds = gutter_bounds.union(&text_bounds); let bounds = gutter_bounds.union(&text_bounds);
let scroll_top = let scroll_top =
@ -711,7 +711,7 @@ impl EditorElement {
&mut self, &mut self,
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
layout: &mut LayoutState, layout: &mut LayoutState,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
let line_height = layout.position_map.line_height; let line_height = layout.position_map.line_height;
@ -782,7 +782,7 @@ impl EditorElement {
}); });
} }
fn paint_diff_hunks(bounds: Bounds<Pixels>, layout: &LayoutState, cx: &mut WindowContext) { fn paint_diff_hunks(bounds: Bounds<Pixels>, layout: &LayoutState, cx: &mut ElementContext) {
let line_height = layout.position_map.line_height; let line_height = layout.position_map.line_height;
let scroll_position = layout.position_map.snapshot.scroll_position(); let scroll_position = layout.position_map.snapshot.scroll_position();
@ -886,7 +886,7 @@ impl EditorElement {
&mut self, &mut self,
text_bounds: Bounds<Pixels>, text_bounds: Bounds<Pixels>,
layout: &mut LayoutState, layout: &mut LayoutState,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
let start_row = layout.visible_display_row_range.start; let start_row = layout.visible_display_row_range.start;
let content_origin = text_bounds.origin + point(layout.gutter_margin, Pixels::ZERO); let content_origin = text_bounds.origin + point(layout.gutter_margin, Pixels::ZERO);
@ -1153,7 +1153,7 @@ impl EditorElement {
&mut self, &mut self,
text_bounds: Bounds<Pixels>, text_bounds: Bounds<Pixels>,
layout: &mut LayoutState, layout: &mut LayoutState,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
let content_origin = text_bounds.origin + point(layout.gutter_margin, Pixels::ZERO); let content_origin = text_bounds.origin + point(layout.gutter_margin, Pixels::ZERO);
let start_row = layout.visible_display_row_range.start; let start_row = layout.visible_display_row_range.start;
@ -1268,7 +1268,7 @@ impl EditorElement {
&mut self, &mut self,
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
layout: &mut LayoutState, layout: &mut LayoutState,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
if layout.mode != EditorMode::Full { if layout.mode != EditorMode::Full {
return; return;
@ -1512,7 +1512,7 @@ impl EditorElement {
layout: &LayoutState, layout: &LayoutState,
content_origin: gpui::Point<Pixels>, content_origin: gpui::Point<Pixels>,
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
let start_row = layout.visible_display_row_range.start; let start_row = layout.visible_display_row_range.start;
let end_row = layout.visible_display_row_range.end; let end_row = layout.visible_display_row_range.end;
@ -1564,7 +1564,7 @@ impl EditorElement {
&mut self, &mut self,
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
layout: &mut LayoutState, layout: &mut LayoutState,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
let scroll_position = layout.position_map.snapshot.scroll_position(); let scroll_position = layout.position_map.snapshot.scroll_position();
let scroll_left = scroll_position.x * layout.position_map.em_width; let scroll_left = scroll_position.x * layout.position_map.em_width;
@ -1814,7 +1814,7 @@ impl EditorElement {
} }
} }
fn compute_layout(&mut self, bounds: Bounds<Pixels>, cx: &mut WindowContext) -> LayoutState { fn compute_layout(&mut self, bounds: Bounds<Pixels>, cx: &mut ElementContext) -> LayoutState {
self.editor.update(cx, |editor, cx| { self.editor.update(cx, |editor, cx| {
let snapshot = editor.snapshot(cx); let snapshot = editor.snapshot(cx);
let style = self.style.clone(); let style = self.style.clone();
@ -2083,7 +2083,9 @@ impl EditorElement {
.width; .width;
let scroll_width = longest_line_width.max(max_visible_line_width) + overscroll.width; let scroll_width = longest_line_width.max(max_visible_line_width) + overscroll.width;
let (scroll_width, blocks) = cx.with_element_id(Some("editor_blocks"), |cx| { let editor_view = cx.view().clone();
let (scroll_width, blocks) = cx.with_element_context(|cx| {
cx.with_element_id(Some("editor_blocks"), |cx| {
self.layout_blocks( self.layout_blocks(
start_row..end_row, start_row..end_row,
&snapshot, &snapshot,
@ -2097,8 +2099,10 @@ impl EditorElement {
&style, &style,
&line_layouts, &line_layouts,
editor, editor,
editor_view,
cx, cx,
) )
})
}); });
let scroll_max = point( let scroll_max = point(
@ -2174,15 +2178,19 @@ impl EditorElement {
cx, cx,
); );
let fold_indicators = cx.with_element_id(Some("gutter_fold_indicators"), |cx| { let editor_view = cx.view().clone();
let fold_indicators = cx.with_element_context(|cx| {
cx.with_element_id(Some("gutter_fold_indicators"), |_cx| {
editor.render_fold_indicators( editor.render_fold_indicators(
fold_statuses, fold_statuses,
&style, &style,
editor.gutter_hovered, editor.gutter_hovered,
line_height, line_height,
gutter_margin, gutter_margin,
cx, editor_view,
) )
})
}); });
let invisible_symbol_font_size = font_size / 2.; let invisible_symbol_font_size = font_size / 2.;
@ -2273,7 +2281,8 @@ impl EditorElement {
style: &EditorStyle, style: &EditorStyle,
line_layouts: &[LineWithInvisibles], line_layouts: &[LineWithInvisibles],
editor: &mut Editor, editor: &mut Editor,
cx: &mut ViewContext<Editor>, editor_view: View<Editor>,
cx: &mut ElementContext,
) -> (Pixels, Vec<BlockLayout>) { ) -> (Pixels, Vec<BlockLayout>) {
let mut block_id = 0; let mut block_id = 0;
let (fixed_blocks, non_fixed_blocks) = snapshot let (fixed_blocks, non_fixed_blocks) = snapshot
@ -2287,7 +2296,7 @@ impl EditorElement {
available_space: Size<AvailableSpace>, available_space: Size<AvailableSpace>,
block_id: usize, block_id: usize,
editor: &mut Editor, editor: &mut Editor,
cx: &mut ViewContext<Editor>| { cx: &mut ElementContext| {
let mut element = match block { let mut element = match block {
TransformBlock::Custom(block) => { TransformBlock::Custom(block) => {
let align_to = block let align_to = block
@ -2306,13 +2315,14 @@ impl EditorElement {
}; };
block.render(&mut BlockContext { block.render(&mut BlockContext {
view_context: cx, context: cx,
anchor_x, anchor_x,
gutter_padding, gutter_padding,
line_height, line_height,
gutter_width, gutter_width,
em_width, em_width,
block_id, block_id,
view: editor_view.clone(),
editor_style: &self.style, editor_style: &self.style,
}) })
} }
@ -2504,7 +2514,7 @@ impl EditorElement {
&mut self, &mut self,
interactive_bounds: &InteractiveBounds, interactive_bounds: &InteractiveBounds,
layout: &LayoutState, layout: &LayoutState,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
cx.on_mouse_event({ cx.on_mouse_event({
let position_map = layout.position_map.clone(); let position_map = layout.position_map.clone();
@ -2564,7 +2574,7 @@ impl EditorElement {
gutter_bounds: Bounds<Pixels>, gutter_bounds: Bounds<Pixels>,
text_bounds: Bounds<Pixels>, text_bounds: Bounds<Pixels>,
layout: &LayoutState, layout: &LayoutState,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
let interactive_bounds = InteractiveBounds { let interactive_bounds = InteractiveBounds {
bounds: bounds.intersect(&cx.content_mask().bounds), bounds: bounds.intersect(&cx.content_mask().bounds),
@ -2787,7 +2797,7 @@ impl LineWithInvisibles {
content_origin: gpui::Point<Pixels>, content_origin: gpui::Point<Pixels>,
whitespace_setting: ShowWhitespaceSetting, whitespace_setting: ShowWhitespaceSetting,
selection_ranges: &[Range<DisplayPoint>], selection_ranges: &[Range<DisplayPoint>],
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
let line_height = layout.position_map.line_height; let line_height = layout.position_map.line_height;
let line_y = line_height * row as f32 - layout.position_map.scroll_position.y; let line_y = line_height * row as f32 - layout.position_map.scroll_position.y;
@ -2821,7 +2831,7 @@ impl LineWithInvisibles {
row: u32, row: u32,
line_height: Pixels, line_height: Pixels,
whitespace_setting: ShowWhitespaceSetting, whitespace_setting: ShowWhitespaceSetting,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
let allowed_invisibles_regions = match whitespace_setting { let allowed_invisibles_regions = match whitespace_setting {
ShowWhitespaceSetting::None => return, ShowWhitespaceSetting::None => return,
@ -2870,7 +2880,7 @@ impl Element for EditorElement {
fn request_layout( fn request_layout(
&mut self, &mut self,
_element_state: Option<Self::State>, _element_state: Option<Self::State>,
cx: &mut gpui::WindowContext, cx: &mut gpui::ElementContext,
) -> (gpui::LayoutId, Self::State) { ) -> (gpui::LayoutId, Self::State) {
cx.with_view_id(self.editor.entity_id(), |cx| { cx.with_view_id(self.editor.entity_id(), |cx| {
self.editor.update(cx, |editor, cx| { self.editor.update(cx, |editor, cx| {
@ -2882,34 +2892,36 @@ impl Element for EditorElement {
let mut style = Style::default(); let mut style = Style::default();
style.size.width = relative(1.).into(); style.size.width = relative(1.).into();
style.size.height = self.style.text.line_height_in_pixels(rem_size).into(); style.size.height = self.style.text.line_height_in_pixels(rem_size).into();
cx.request_layout(&style, None) cx.with_element_context(|cx| cx.request_layout(&style, None))
} }
EditorMode::AutoHeight { max_lines } => { EditorMode::AutoHeight { max_lines } => {
let editor_handle = cx.view().clone(); let editor_handle = cx.view().clone();
let max_line_number_width = let max_line_number_width =
self.max_line_number_width(&editor.snapshot(cx), cx); self.max_line_number_width(&editor.snapshot(cx), cx);
cx.request_measured_layout( cx.with_element_context(|cx| {
Style::default(), cx.request_measured_layout(
move |known_dimensions, _, cx| { Style::default(),
editor_handle move |known_dimensions, _, cx| {
.update(cx, |editor, cx| { editor_handle
compute_auto_height_layout( .update(cx, |editor, cx| {
editor, compute_auto_height_layout(
max_lines, editor,
max_line_number_width, max_lines,
known_dimensions, max_line_number_width,
cx, known_dimensions,
) cx,
}) )
.unwrap_or_default() })
}, .unwrap_or_default()
) },
)
})
} }
EditorMode::Full => { EditorMode::Full => {
let mut style = Style::default(); let mut style = Style::default();
style.size.width = relative(1.).into(); style.size.width = relative(1.).into();
style.size.height = relative(1.).into(); style.size.height = relative(1.).into();
cx.request_layout(&style, None) cx.with_element_context(|cx| cx.request_layout(&style, None))
} }
}; };
@ -2922,7 +2934,7 @@ impl Element for EditorElement {
&mut self, &mut self,
bounds: Bounds<gpui::Pixels>, bounds: Bounds<gpui::Pixels>,
_element_state: &mut Self::State, _element_state: &mut Self::State,
cx: &mut gpui::WindowContext, cx: &mut gpui::ElementContext,
) { ) {
let editor = self.editor.clone(); let editor = self.editor.clone();
@ -3204,7 +3216,7 @@ impl Cursor {
} }
} }
pub fn paint(&self, origin: gpui::Point<Pixels>, cx: &mut WindowContext) { pub fn paint(&self, origin: gpui::Point<Pixels>, cx: &mut ElementContext) {
let bounds = match self.shape { let bounds = match self.shape {
CursorShape::Bar => Bounds { CursorShape::Bar => Bounds {
origin: self.origin + origin, origin: self.origin + origin,
@ -3284,7 +3296,7 @@ pub struct HighlightedRangeLine {
} }
impl HighlightedRange { impl HighlightedRange {
pub fn paint(&self, bounds: Bounds<Pixels>, cx: &mut WindowContext) { pub fn paint(&self, bounds: Bounds<Pixels>, cx: &mut ElementContext) {
if self.lines.len() >= 2 && self.lines[0].start_x > self.lines[1].end_x { if self.lines.len() >= 2 && self.lines[0].start_x > self.lines[1].end_x {
self.paint_lines(self.start_y, &self.lines[0..1], bounds, cx); self.paint_lines(self.start_y, &self.lines[0..1], bounds, cx);
self.paint_lines( self.paint_lines(
@ -3303,7 +3315,7 @@ impl HighlightedRange {
start_y: Pixels, start_y: Pixels,
lines: &[HighlightedRangeLine], lines: &[HighlightedRangeLine],
_bounds: Bounds<Pixels>, _bounds: Bounds<Pixels>,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
if lines.is_empty() { if lines.is_empty() {
return; return;
@ -3521,14 +3533,16 @@ mod tests {
.unwrap(); .unwrap();
let state = cx let state = cx
.update_window(window.into(), |view, cx| { .update_window(window.into(), |view, cx| {
cx.with_view_id(view.entity_id(), |cx| { cx.with_element_context(|cx| {
element.compute_layout( cx.with_view_id(view.entity_id(), |cx| {
Bounds { element.compute_layout(
origin: point(px(500.), px(500.)), Bounds {
size: size(px(500.), px(500.)), origin: point(px(500.), px(500.)),
}, size: size(px(500.), px(500.)),
cx, },
) cx,
)
})
}) })
}) })
.unwrap(); .unwrap();
@ -3615,14 +3629,16 @@ mod tests {
let state = cx let state = cx
.update_window(window.into(), |view, cx| { .update_window(window.into(), |view, cx| {
cx.with_view_id(view.entity_id(), |cx| { cx.with_element_context(|cx| {
element.compute_layout( cx.with_view_id(view.entity_id(), |cx| {
Bounds { element.compute_layout(
origin: point(px(500.), px(500.)), Bounds {
size: size(px(500.), px(500.)), origin: point(px(500.), px(500.)),
}, size: size(px(500.), px(500.)),
cx, },
) cx,
)
})
}) })
}) })
.unwrap(); .unwrap();
@ -3679,14 +3695,16 @@ mod tests {
let mut element = EditorElement::new(&editor, style); let mut element = EditorElement::new(&editor, style);
let state = cx let state = cx
.update_window(window.into(), |view, cx| { .update_window(window.into(), |view, cx| {
cx.with_view_id(view.entity_id(), |cx| { cx.with_element_context(|cx| {
element.compute_layout( cx.with_view_id(view.entity_id(), |cx| {
Bounds { element.compute_layout(
origin: point(px(500.), px(500.)), Bounds {
size: size(px(500.), px(500.)), origin: point(px(500.), px(500.)),
}, size: size(px(500.), px(500.)),
cx, },
) cx,
)
})
}) })
}) })
.unwrap(); .unwrap();
@ -3704,8 +3722,10 @@ mod tests {
// Don't panic. // Don't panic.
let bounds = Bounds::<Pixels>::new(Default::default(), size); let bounds = Bounds::<Pixels>::new(Default::default(), size);
cx.update_window(window.into(), |_, cx| element.paint(bounds, &mut (), cx)) cx.update_window(window.into(), |_, cx| {
.unwrap() cx.with_element_context(|cx| element.paint(bounds, &mut (), cx))
})
.unwrap()
} }
#[gpui::test] #[gpui::test]
@ -3880,13 +3900,15 @@ mod tests {
.unwrap(); .unwrap();
let layout_state = cx let layout_state = cx
.update_window(window.into(), |_, cx| { .update_window(window.into(), |_, cx| {
element.compute_layout( cx.with_element_context(|cx| {
Bounds { element.compute_layout(
origin: point(px(500.), px(500.)), Bounds {
size: size(px(500.), px(500.)), origin: point(px(500.), px(500.)),
}, size: size(px(500.), px(500.)),
cx, },
) cx,
)
})
}) })
.unwrap(); .unwrap();

View file

@ -640,8 +640,11 @@ impl<'a> VisualTestContext {
.as_ref() .as_ref()
.expect("Can't draw to this window without a root view") .expect("Can't draw to this window without a root view")
.entity_id(); .entity_id();
cx.with_view_id(entity_id, |cx| {
f(cx).draw(origin, space, cx); cx.with_element_context(|cx| {
cx.with_view_id(entity_id, |cx| {
f(cx).draw(origin, space, cx);
})
}); });
cx.refresh(); cx.refresh();

View file

@ -35,12 +35,12 @@
//! your own custom layout algorithm or rendering a code editor. //! your own custom layout algorithm or rendering a code editor.
use crate::{ use crate::{
util::FluentBuilder, ArenaBox, AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, util::FluentBuilder, ArenaBox, AvailableSpace, Bounds, ElementContext, ElementId, LayoutId,
Pixels, Point, Size, ViewContext, WindowContext, ELEMENT_ARENA, Pixels, Point, Size, ViewContext, WindowContext, ELEMENT_ARENA,
}; };
use derive_more::{Deref, DerefMut}; use derive_more::{Deref, DerefMut};
pub(crate) use smallvec::SmallVec; pub(crate) use smallvec::SmallVec;
use std::{any::Any, fmt::Debug}; use std::{any::Any, fmt::Debug, ops::DerefMut};
/// Implemented by types that participate in laying out and painting the contents of a window. /// Implemented by types that participate in laying out and painting the contents of a window.
/// Elements form a tree and are laid out according to web-based layout rules, as implemented by Taffy. /// Elements form a tree and are laid out according to web-based layout rules, as implemented by Taffy.
@ -56,12 +56,12 @@ pub trait Element: 'static + IntoElement {
fn request_layout( fn request_layout(
&mut self, &mut self,
state: Option<Self::State>, state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, Self::State); ) -> (LayoutId, Self::State);
/// Once layout has been completed, this method will be called to paint the element to the screen. /// Once layout has been completed, this method will be called to paint the element to the screen.
/// The state argument is the same state that was returned from [`Element::request_layout()`]. /// The state argument is the same state that was returned from [`Element::request_layout()`].
fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext); fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut ElementContext);
/// Convert this element into a dynamically-typed [`AnyElement`]. /// Convert this element into a dynamically-typed [`AnyElement`].
fn into_any(self) -> AnyElement { fn into_any(self) -> AnyElement {
@ -95,8 +95,8 @@ pub trait IntoElement: Sized {
self, self,
origin: Point<Pixels>, origin: Point<Pixels>,
available_space: Size<T>, available_space: Size<T>,
cx: &mut WindowContext, cx: &mut ElementContext,
f: impl FnOnce(&mut <Self::Element as Element>::State, &mut WindowContext) -> R, f: impl FnOnce(&mut <Self::Element as Element>::State, &mut ElementContext) -> R,
) -> R ) -> R
where where
T: Clone + Default + Debug + Into<AvailableSpace>, T: Clone + Default + Debug + Into<AvailableSpace>,
@ -193,14 +193,19 @@ impl<C: RenderOnce> Element for Component<C> {
fn request_layout( fn request_layout(
&mut self, &mut self,
_: Option<Self::State>, _: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
let mut element = self.0.take().unwrap().render(cx).into_any_element(); let mut element = self
.0
.take()
.unwrap()
.render(cx.deref_mut())
.into_any_element();
let layout_id = element.request_layout(cx); let layout_id = element.request_layout(cx);
(layout_id, element) (layout_id, element)
} }
fn paint(&mut self, _: Bounds<Pixels>, element: &mut Self::State, cx: &mut WindowContext) { fn paint(&mut self, _: Bounds<Pixels>, element: &mut Self::State, cx: &mut ElementContext) {
element.paint(cx) element.paint(cx)
} }
} }
@ -224,21 +229,21 @@ pub(crate) struct GlobalElementId(SmallVec<[ElementId; 32]>);
trait ElementObject { trait ElementObject {
fn element_id(&self) -> Option<ElementId>; fn element_id(&self) -> Option<ElementId>;
fn request_layout(&mut self, cx: &mut WindowContext) -> LayoutId; fn request_layout(&mut self, cx: &mut ElementContext) -> LayoutId;
fn paint(&mut self, cx: &mut WindowContext); fn paint(&mut self, cx: &mut ElementContext);
fn measure( fn measure(
&mut self, &mut self,
available_space: Size<AvailableSpace>, available_space: Size<AvailableSpace>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> Size<Pixels>; ) -> Size<Pixels>;
fn draw( fn draw(
&mut self, &mut self,
origin: Point<Pixels>, origin: Point<Pixels>,
available_space: Size<AvailableSpace>, available_space: Size<AvailableSpace>,
cx: &mut WindowContext, cx: &mut ElementContext,
); );
} }
@ -276,7 +281,7 @@ impl<E: Element> DrawableElement<E> {
self.element.as_ref()?.element_id() self.element.as_ref()?.element_id()
} }
fn request_layout(&mut self, cx: &mut WindowContext) -> LayoutId { fn request_layout(&mut self, cx: &mut ElementContext) -> LayoutId {
let (layout_id, frame_state) = if let Some(id) = self.element.as_ref().unwrap().element_id() let (layout_id, frame_state) = if let Some(id) = self.element.as_ref().unwrap().element_id()
{ {
let layout_id = cx.with_element_state(id, |element_state, cx| { let layout_id = cx.with_element_state(id, |element_state, cx| {
@ -298,7 +303,7 @@ impl<E: Element> DrawableElement<E> {
layout_id layout_id
} }
fn paint(mut self, cx: &mut WindowContext) -> Option<E::State> { fn paint(mut self, cx: &mut ElementContext) -> Option<E::State> {
match self.phase { match self.phase {
ElementDrawPhase::LayoutRequested { ElementDrawPhase::LayoutRequested {
layout_id, layout_id,
@ -343,7 +348,7 @@ impl<E: Element> DrawableElement<E> {
fn measure( fn measure(
&mut self, &mut self,
available_space: Size<AvailableSpace>, available_space: Size<AvailableSpace>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> Size<Pixels> { ) -> Size<Pixels> {
if matches!(&self.phase, ElementDrawPhase::Start) { if matches!(&self.phase, ElementDrawPhase::Start) {
self.request_layout(cx); self.request_layout(cx);
@ -384,7 +389,7 @@ impl<E: Element> DrawableElement<E> {
mut self, mut self,
origin: Point<Pixels>, origin: Point<Pixels>,
available_space: Size<AvailableSpace>, available_space: Size<AvailableSpace>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> Option<E::State> { ) -> Option<E::State> {
self.measure(available_space, cx); self.measure(available_space, cx);
cx.with_absolute_element_offset(origin, |cx| self.paint(cx)) cx.with_absolute_element_offset(origin, |cx| self.paint(cx))
@ -400,18 +405,18 @@ where
self.as_ref().unwrap().element_id() self.as_ref().unwrap().element_id()
} }
fn request_layout(&mut self, cx: &mut WindowContext) -> LayoutId { fn request_layout(&mut self, cx: &mut ElementContext) -> LayoutId {
DrawableElement::request_layout(self.as_mut().unwrap(), cx) DrawableElement::request_layout(self.as_mut().unwrap(), cx)
} }
fn paint(&mut self, cx: &mut WindowContext) { fn paint(&mut self, cx: &mut ElementContext) {
DrawableElement::paint(self.take().unwrap(), cx); DrawableElement::paint(self.take().unwrap(), cx);
} }
fn measure( fn measure(
&mut self, &mut self,
available_space: Size<AvailableSpace>, available_space: Size<AvailableSpace>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> Size<Pixels> { ) -> Size<Pixels> {
DrawableElement::measure(self.as_mut().unwrap(), available_space, cx) DrawableElement::measure(self.as_mut().unwrap(), available_space, cx)
} }
@ -420,7 +425,7 @@ where
&mut self, &mut self,
origin: Point<Pixels>, origin: Point<Pixels>,
available_space: Size<AvailableSpace>, available_space: Size<AvailableSpace>,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
DrawableElement::draw(self.take().unwrap(), origin, available_space, cx); DrawableElement::draw(self.take().unwrap(), origin, available_space, cx);
} }
@ -443,12 +448,12 @@ impl AnyElement {
/// Request the layout ID of the element stored in this `AnyElement`. /// Request the layout ID of the element stored in this `AnyElement`.
/// Used for laying out child elements in a parent element. /// Used for laying out child elements in a parent element.
pub fn request_layout(&mut self, cx: &mut WindowContext) -> LayoutId { pub fn request_layout(&mut self, cx: &mut ElementContext) -> LayoutId {
self.0.request_layout(cx) self.0.request_layout(cx)
} }
/// Paints the element stored in this `AnyElement`. /// Paints the element stored in this `AnyElement`.
pub fn paint(&mut self, cx: &mut WindowContext) { pub fn paint(&mut self, cx: &mut ElementContext) {
self.0.paint(cx) self.0.paint(cx)
} }
@ -456,7 +461,7 @@ impl AnyElement {
pub fn measure( pub fn measure(
&mut self, &mut self,
available_space: Size<AvailableSpace>, available_space: Size<AvailableSpace>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> Size<Pixels> { ) -> Size<Pixels> {
self.0.measure(available_space, cx) self.0.measure(available_space, cx)
} }
@ -466,7 +471,7 @@ impl AnyElement {
&mut self, &mut self,
origin: Point<Pixels>, origin: Point<Pixels>,
available_space: Size<AvailableSpace>, available_space: Size<AvailableSpace>,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
self.0.draw(origin, available_space, cx) self.0.draw(origin, available_space, cx)
} }
@ -483,13 +488,13 @@ impl Element for AnyElement {
fn request_layout( fn request_layout(
&mut self, &mut self,
_: Option<Self::State>, _: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
let layout_id = self.request_layout(cx); let layout_id = self.request_layout(cx);
(layout_id, ()) (layout_id, ())
} }
fn paint(&mut self, _: Bounds<Pixels>, _: &mut Self::State, cx: &mut WindowContext) { fn paint(&mut self, _: Bounds<Pixels>, _: &mut Self::State, cx: &mut ElementContext) {
self.paint(cx) self.paint(cx)
} }
} }
@ -531,7 +536,7 @@ impl Element for () {
fn request_layout( fn request_layout(
&mut self, &mut self,
_state: Option<Self::State>, _state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
(cx.request_layout(&crate::Style::default(), None), ()) (cx.request_layout(&crate::Style::default(), None), ())
} }
@ -540,7 +545,7 @@ impl Element for () {
&mut self, &mut self,
_bounds: Bounds<Pixels>, _bounds: Bounds<Pixels>,
_state: &mut Self::State, _state: &mut Self::State,
_cx: &mut WindowContext, _cx: &mut ElementContext,
) { ) {
} }
} }

View file

@ -1,10 +1,10 @@
use refineable::Refineable as _; use refineable::Refineable as _;
use crate::{Bounds, Element, IntoElement, Pixels, Style, StyleRefinement, Styled, WindowContext}; use crate::{Bounds, Element, ElementContext, IntoElement, Pixels, Style, StyleRefinement, Styled};
/// Construct a canvas element with the given paint callback. /// Construct a canvas element with the given paint callback.
/// Useful for adding short term custom drawing to a view. /// Useful for adding short term custom drawing to a view.
pub fn canvas(callback: impl 'static + FnOnce(&Bounds<Pixels>, &mut WindowContext)) -> Canvas { pub fn canvas(callback: impl 'static + FnOnce(&Bounds<Pixels>, &mut ElementContext)) -> Canvas {
Canvas { Canvas {
paint_callback: Some(Box::new(callback)), paint_callback: Some(Box::new(callback)),
style: StyleRefinement::default(), style: StyleRefinement::default(),
@ -14,7 +14,7 @@ pub fn canvas(callback: impl 'static + FnOnce(&Bounds<Pixels>, &mut WindowContex
/// A canvas element, meant for accessing the low level paint API without defining a whole /// A canvas element, meant for accessing the low level paint API without defining a whole
/// custom element /// custom element
pub struct Canvas { pub struct Canvas {
paint_callback: Option<Box<dyn FnOnce(&Bounds<Pixels>, &mut WindowContext)>>, paint_callback: Option<Box<dyn FnOnce(&Bounds<Pixels>, &mut ElementContext)>>,
style: StyleRefinement, style: StyleRefinement,
} }
@ -36,7 +36,7 @@ impl Element for Canvas {
fn request_layout( fn request_layout(
&mut self, &mut self,
_: Option<Self::State>, _: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (crate::LayoutId, Self::State) { ) -> (crate::LayoutId, Self::State) {
let mut style = Style::default(); let mut style = Style::default();
style.refine(&self.style); style.refine(&self.style);
@ -44,7 +44,7 @@ impl Element for Canvas {
(layout_id, style) (layout_id, style)
} }
fn paint(&mut self, bounds: Bounds<Pixels>, style: &mut Style, cx: &mut WindowContext) { fn paint(&mut self, bounds: Bounds<Pixels>, style: &mut Style, cx: &mut ElementContext) {
style.paint(bounds, cx, |cx| { style.paint(bounds, cx, |cx| {
(self.paint_callback.take().unwrap())(&bounds, cx) (self.paint_callback.take().unwrap())(&bounds, cx)
}); });

View file

@ -23,12 +23,11 @@
//! //!
use crate::{ use crate::{
point, px, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, BorrowAppContext, point, px, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, Bounds, ClickEvent,
BorrowWindow, Bounds, ClickEvent, DispatchPhase, Element, ElementId, FocusHandle, IntoElement, DispatchPhase, Element, ElementContext, ElementId, FocusHandle, IntoElement, IsZero,
IsZero, KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent, KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent, MouseMoveEvent,
MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Point, Render, ScrollWheelEvent, MouseUpEvent, ParentElement, Pixels, Point, Render, ScrollWheelEvent, SharedString, Size,
SharedString, Size, StackingOrder, Style, StyleRefinement, Styled, Task, View, Visibility, StackingOrder, Style, StyleRefinement, Styled, Task, View, Visibility, WindowContext,
WindowContext,
}; };
use collections::HashMap; use collections::HashMap;
@ -41,6 +40,7 @@ use std::{
fmt::Debug, fmt::Debug,
marker::PhantomData, marker::PhantomData,
mem, mem,
ops::DerefMut,
rc::Rc, rc::Rc,
time::Duration, time::Duration,
}; };
@ -1052,7 +1052,7 @@ impl Element for Div {
fn request_layout( fn request_layout(
&mut self, &mut self,
element_state: Option<Self::State>, element_state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
let mut child_layout_ids = SmallVec::new(); let mut child_layout_ids = SmallVec::new();
let (layout_id, interactive_state) = self.interactivity.layout( let (layout_id, interactive_state) = self.interactivity.layout(
@ -1082,7 +1082,7 @@ impl Element for Div {
&mut self, &mut self,
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
element_state: &mut Self::State, element_state: &mut Self::State,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
let mut child_min = point(Pixels::MAX, Pixels::MAX); let mut child_min = point(Pixels::MAX, Pixels::MAX);
let mut child_max = Point::default(); let mut child_max = Point::default();
@ -1233,8 +1233,8 @@ impl Interactivity {
pub fn layout( pub fn layout(
&mut self, &mut self,
element_state: Option<InteractiveElementState>, element_state: Option<InteractiveElementState>,
cx: &mut WindowContext, cx: &mut ElementContext,
f: impl FnOnce(Style, &mut WindowContext) -> LayoutId, f: impl FnOnce(Style, &mut ElementContext) -> LayoutId,
) -> (LayoutId, InteractiveElementState) { ) -> (LayoutId, InteractiveElementState) {
let mut element_state = element_state.unwrap_or_default(); let mut element_state = element_state.unwrap_or_default();
@ -1281,8 +1281,8 @@ impl Interactivity {
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
content_size: Size<Pixels>, content_size: Size<Pixels>,
element_state: &mut InteractiveElementState, element_state: &mut InteractiveElementState,
cx: &mut WindowContext, cx: &mut ElementContext,
f: impl FnOnce(&Style, Point<Pixels>, &mut WindowContext), f: impl FnOnce(&Style, Point<Pixels>, &mut ElementContext),
) { ) {
let style = self.compute_style(Some(bounds), element_state, cx); let style = self.compute_style(Some(bounds), element_state, cx);
let z_index = style.z_index.unwrap_or(0); let z_index = style.z_index.unwrap_or(0);
@ -1295,7 +1295,7 @@ impl Interactivity {
.insert(debug_selector.clone(), bounds); .insert(debug_selector.clone(), bounds);
} }
let paint_hover_group_handler = |cx: &mut WindowContext| { let paint_hover_group_handler = |cx: &mut ElementContext| {
let hover_group_bounds = self let hover_group_bounds = self
.group_hover_style .group_hover_style
.as_ref() .as_ref()
@ -1319,7 +1319,7 @@ impl Interactivity {
} }
cx.with_z_index(z_index, |cx| { cx.with_z_index(z_index, |cx| {
style.paint(bounds, cx, |cx| { style.paint(bounds, cx, |cx: &mut ElementContext| {
cx.with_text_style(style.text_style().cloned(), |cx| { cx.with_text_style(style.text_style().cloned(), |cx| {
cx.with_content_mask(style.overflow_mask(bounds, cx.rem_size()), |cx| { cx.with_content_mask(style.overflow_mask(bounds, cx.rem_size()), |cx| {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
@ -1333,7 +1333,7 @@ impl Interactivity {
let element_id = format!("{:?}", self.element_id.as_ref().unwrap()); let element_id = format!("{:?}", self.element_id.as_ref().unwrap());
let str_len = element_id.len(); let str_len = element_id.len();
let render_debug_text = |cx: &mut WindowContext| { let render_debug_text = |cx: &mut ElementContext| {
if let Some(text) = cx if let Some(text) = cx
.text_system() .text_system()
.shape_text( .shape_text(
@ -1540,12 +1540,17 @@ impl Interactivity {
let mut can_drop = true; let mut can_drop = true;
if let Some(predicate) = &can_drop_predicate { if let Some(predicate) = &can_drop_predicate {
can_drop = can_drop = predicate(
predicate(drag.value.as_ref(), cx); drag.value.as_ref(),
cx.deref_mut(),
);
} }
if can_drop { if can_drop {
listener(drag.value.as_ref(), cx); listener(
drag.value.as_ref(),
cx.deref_mut(),
);
cx.refresh(); cx.refresh();
cx.stop_propagation(); cx.stop_propagation();
} }
@ -1676,7 +1681,7 @@ impl Interactivity {
*was_hovered = is_hovered; *was_hovered = is_hovered;
drop(was_hovered); drop(was_hovered);
hover_listener(&is_hovered, cx); hover_listener(&is_hovered, cx.deref_mut());
} }
}); });
} }
@ -1897,7 +1902,7 @@ impl Interactivity {
&self, &self,
bounds: Option<Bounds<Pixels>>, bounds: Option<Bounds<Pixels>>,
element_state: &mut InteractiveElementState, element_state: &mut InteractiveElementState,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> Style { ) -> Style {
let mut style = Style::default(); let mut style = Style::default();
style.refine(&self.base_style); style.refine(&self.base_style);
@ -1921,7 +1926,9 @@ impl Interactivity {
let mouse_position = cx.mouse_position(); let mouse_position = cx.mouse_position();
if !cx.has_active_drag() { if !cx.has_active_drag() {
if let Some(group_hover) = self.group_hover_style.as_ref() { if let Some(group_hover) = self.group_hover_style.as_ref() {
if let Some(group_bounds) = GroupBounds::get(&group_hover.group, cx) { if let Some(group_bounds) =
GroupBounds::get(&group_hover.group, cx.deref_mut())
{
if group_bounds.contains(&mouse_position) if group_bounds.contains(&mouse_position)
&& cx.was_top_layer(&mouse_position, cx.stacking_order()) && cx.was_top_layer(&mouse_position, cx.stacking_order())
{ {
@ -1944,13 +1951,13 @@ impl Interactivity {
if let Some(drag) = cx.active_drag.take() { if let Some(drag) = cx.active_drag.take() {
let mut can_drop = true; let mut can_drop = true;
if let Some(can_drop_predicate) = &self.can_drop_predicate { if let Some(can_drop_predicate) = &self.can_drop_predicate {
can_drop = can_drop_predicate(drag.value.as_ref(), cx); can_drop = can_drop_predicate(drag.value.as_ref(), cx.deref_mut());
} }
if can_drop { if can_drop {
for (state_type, group_drag_style) in &self.group_drag_over_styles { for (state_type, group_drag_style) in &self.group_drag_over_styles {
if let Some(group_bounds) = if let Some(group_bounds) =
GroupBounds::get(&group_drag_style.group, cx) GroupBounds::get(&group_drag_style.group, cx.deref_mut())
{ {
if *state_type == drag.value.as_ref().type_id() if *state_type == drag.value.as_ref().type_id()
&& group_bounds.contains(&mouse_position) && group_bounds.contains(&mouse_position)
@ -2096,12 +2103,12 @@ where
fn request_layout( fn request_layout(
&mut self, &mut self,
state: Option<Self::State>, state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
self.element.request_layout(state, cx) self.element.request_layout(state, cx)
} }
fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) { fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut ElementContext) {
self.element.paint(bounds, state, cx) self.element.paint(bounds, state, cx)
} }
} }
@ -2171,12 +2178,12 @@ where
fn request_layout( fn request_layout(
&mut self, &mut self,
state: Option<Self::State>, state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
self.element.request_layout(state, cx) self.element.request_layout(state, cx)
} }
fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) { fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut ElementContext) {
self.element.paint(bounds, state, cx) self.element.paint(bounds, state, cx)
} }
} }

View file

@ -1,9 +1,9 @@
use std::sync::Arc; use std::sync::Arc;
use crate::{ use crate::{
point, size, BorrowWindow, Bounds, DevicePixels, Element, ImageData, InteractiveElement, point, size, Bounds, DevicePixels, Element, ElementContext, ImageData, InteractiveElement,
InteractiveElementState, Interactivity, IntoElement, LayoutId, Pixels, SharedUrl, Size, InteractiveElementState, Interactivity, IntoElement, LayoutId, Pixels, SharedUrl, Size,
StyleRefinement, Styled, WindowContext, StyleRefinement, Styled,
}; };
use futures::FutureExt; use futures::FutureExt;
use media::core_video::CVImageBuffer; use media::core_video::CVImageBuffer;
@ -81,7 +81,7 @@ impl Element for Img {
fn request_layout( fn request_layout(
&mut self, &mut self,
element_state: Option<Self::State>, element_state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
self.interactivity self.interactivity
.layout(element_state, cx, |style, cx| cx.request_layout(&style, [])) .layout(element_state, cx, |style, cx| cx.request_layout(&style, []))
@ -91,7 +91,7 @@ impl Element for Img {
&mut self, &mut self,
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
element_state: &mut Self::State, element_state: &mut Self::State,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
let source = self.source.clone(); let source = self.source.clone();
self.interactivity.paint( self.interactivity.paint(

View file

@ -7,9 +7,9 @@
//! If all of your elements are the same height, see [`UniformList`] for a simpler API //! If all of your elements are the same height, see [`UniformList`] for a simpler API
use crate::{ use crate::{
point, px, AnyElement, AvailableSpace, BorrowAppContext, BorrowWindow, Bounds, ContentMask, point, px, AnyElement, AvailableSpace, Bounds, ContentMask, DispatchPhase, Element,
DispatchPhase, Element, IntoElement, Pixels, Point, ScrollWheelEvent, Size, Style, IntoElement, Pixels, Point, ScrollWheelEvent, Size, Style, StyleRefinement, Styled,
StyleRefinement, Styled, WindowContext, WindowContext,
}; };
use collections::VecDeque; use collections::VecDeque;
use refineable::Refineable as _; use refineable::Refineable as _;
@ -359,7 +359,7 @@ impl Element for List {
fn request_layout( fn request_layout(
&mut self, &mut self,
_state: Option<Self::State>, _state: Option<Self::State>,
cx: &mut crate::WindowContext, cx: &mut crate::ElementContext,
) -> (crate::LayoutId, Self::State) { ) -> (crate::LayoutId, Self::State) {
let mut style = Style::default(); let mut style = Style::default();
style.refine(&self.style); style.refine(&self.style);
@ -373,7 +373,7 @@ impl Element for List {
&mut self, &mut self,
bounds: Bounds<crate::Pixels>, bounds: Bounds<crate::Pixels>,
_state: &mut Self::State, _state: &mut Self::State,
cx: &mut crate::WindowContext, cx: &mut crate::ElementContext,
) { ) {
let state = &mut *self.state.0.borrow_mut(); let state = &mut *self.state.0.borrow_mut();

View file

@ -2,8 +2,8 @@ use smallvec::SmallVec;
use taffy::style::{Display, Position}; use taffy::style::{Display, Position};
use crate::{ use crate::{
point, AnyElement, BorrowWindow, Bounds, Element, IntoElement, LayoutId, ParentElement, Pixels, point, AnyElement, Bounds, Element, ElementContext, IntoElement, LayoutId, ParentElement,
Point, Size, Style, WindowContext, Pixels, Point, Size, Style,
}; };
/// The state that the overlay element uses to track its children. /// The state that the overlay element uses to track its children.
@ -74,7 +74,7 @@ impl Element for Overlay {
fn request_layout( fn request_layout(
&mut self, &mut self,
_: Option<Self::State>, _: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (crate::LayoutId, Self::State) { ) -> (crate::LayoutId, Self::State) {
let child_layout_ids = self let child_layout_ids = self
.children .children
@ -97,7 +97,7 @@ impl Element for Overlay {
&mut self, &mut self,
bounds: crate::Bounds<crate::Pixels>, bounds: crate::Bounds<crate::Pixels>,
element_state: &mut Self::State, element_state: &mut Self::State,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
if element_state.child_layout_ids.is_empty() { if element_state.child_layout_ids.is_empty() {
return; return;

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
Bounds, Element, ElementId, InteractiveElement, InteractiveElementState, Interactivity, Bounds, Element, ElementContext, ElementId, InteractiveElement, InteractiveElementState,
IntoElement, LayoutId, Pixels, SharedString, StyleRefinement, Styled, WindowContext, Interactivity, IntoElement, LayoutId, Pixels, SharedString, StyleRefinement, Styled,
}; };
use util::ResultExt; use util::ResultExt;
@ -32,7 +32,7 @@ impl Element for Svg {
fn request_layout( fn request_layout(
&mut self, &mut self,
element_state: Option<Self::State>, element_state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
self.interactivity.layout(element_state, cx, |style, cx| { self.interactivity.layout(element_state, cx, |style, cx| {
cx.request_layout(&style, None) cx.request_layout(&style, None)
@ -43,7 +43,7 @@ impl Element for Svg {
&mut self, &mut self,
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
element_state: &mut Self::State, element_state: &mut Self::State,
cx: &mut WindowContext, cx: &mut ElementContext,
) where ) where
Self: Sized, Self: Sized,
{ {

View file

@ -1,7 +1,8 @@
use crate::{ use crate::{
ActiveTooltip, AnyTooltip, AnyView, Bounds, DispatchPhase, Element, ElementId, HighlightStyle, ActiveTooltip, AnyTooltip, AnyView, Bounds, DispatchPhase, Element, ElementContext, ElementId,
IntoElement, LayoutId, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, Point, HighlightStyle, IntoElement, LayoutId, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels,
SharedString, Size, TextRun, TextStyle, WhiteSpace, WindowContext, WrappedLine, TOOLTIP_DELAY, Point, SharedString, Size, TextRun, TextStyle, WhiteSpace, WindowContext, WrappedLine,
TOOLTIP_DELAY,
}; };
use anyhow::anyhow; use anyhow::anyhow;
use parking_lot::{Mutex, MutexGuard}; use parking_lot::{Mutex, MutexGuard};
@ -21,14 +22,14 @@ impl Element for &'static str {
fn request_layout( fn request_layout(
&mut self, &mut self,
_: Option<Self::State>, _: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
let mut state = TextState::default(); let mut state = TextState::default();
let layout_id = state.layout(SharedString::from(*self), None, cx); let layout_id = state.layout(SharedString::from(*self), None, cx);
(layout_id, state) (layout_id, state)
} }
fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut TextState, cx: &mut WindowContext) { fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut TextState, cx: &mut ElementContext) {
state.paint(bounds, self, cx) state.paint(bounds, self, cx)
} }
} }
@ -51,14 +52,14 @@ impl Element for SharedString {
fn request_layout( fn request_layout(
&mut self, &mut self,
_: Option<Self::State>, _: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
let mut state = TextState::default(); let mut state = TextState::default();
let layout_id = state.layout(self.clone(), None, cx); let layout_id = state.layout(self.clone(), None, cx);
(layout_id, state) (layout_id, state)
} }
fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut TextState, cx: &mut WindowContext) { fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut TextState, cx: &mut ElementContext) {
let text_str: &str = self.as_ref(); let text_str: &str = self.as_ref();
state.paint(bounds, text_str, cx) state.paint(bounds, text_str, cx)
} }
@ -130,14 +131,14 @@ impl Element for StyledText {
fn request_layout( fn request_layout(
&mut self, &mut self,
_: Option<Self::State>, _: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
let mut state = TextState::default(); let mut state = TextState::default();
let layout_id = state.layout(self.text.clone(), self.runs.take(), cx); let layout_id = state.layout(self.text.clone(), self.runs.take(), cx);
(layout_id, state) (layout_id, state)
} }
fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) { fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut ElementContext) {
state.paint(bounds, &self.text, cx) state.paint(bounds, &self.text, cx)
} }
} }
@ -174,7 +175,7 @@ impl TextState {
&mut self, &mut self,
text: SharedString, text: SharedString,
runs: Option<Vec<TextRun>>, runs: Option<Vec<TextRun>>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> LayoutId { ) -> LayoutId {
let text_style = cx.text_style(); let text_style = cx.text_style();
let font_size = text_style.font_size.to_pixels(cx.rem_size()); let font_size = text_style.font_size.to_pixels(cx.rem_size());
@ -249,7 +250,7 @@ impl TextState {
layout_id layout_id
} }
fn paint(&mut self, bounds: Bounds<Pixels>, text: &str, cx: &mut WindowContext) { fn paint(&mut self, bounds: Bounds<Pixels>, text: &str, cx: &mut ElementContext) {
let element_state = self.lock(); let element_state = self.lock();
let element_state = element_state let element_state = element_state
.as_ref() .as_ref()
@ -377,7 +378,7 @@ impl Element for InteractiveText {
fn request_layout( fn request_layout(
&mut self, &mut self,
state: Option<Self::State>, state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
if let Some(InteractiveTextState { if let Some(InteractiveTextState {
mouse_down_index, mouse_down_index,
@ -406,7 +407,7 @@ impl Element for InteractiveText {
} }
} }
fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) { fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut ElementContext) {
if let Some(click_listener) = self.click_listener.take() { if let Some(click_listener) = self.click_listener.take() {
let mouse_position = cx.mouse_position(); let mouse_position = cx.mouse_position();
if let Some(ix) = state.text_state.index_for_position(bounds, mouse_position) { if let Some(ix) = state.text_state.index_for_position(bounds, mouse_position) {

View file

@ -5,7 +5,7 @@
//! elements with uniform height. //! elements with uniform height.
use crate::{ use crate::{
point, px, size, AnyElement, AvailableSpace, BorrowWindow, Bounds, ContentMask, Element, point, px, size, AnyElement, AvailableSpace, Bounds, ContentMask, Element, ElementContext,
ElementId, InteractiveElement, InteractiveElementState, Interactivity, IntoElement, LayoutId, ElementId, InteractiveElement, InteractiveElementState, Interactivity, IntoElement, LayoutId,
Pixels, Render, Size, StyleRefinement, Styled, View, ViewContext, WindowContext, Pixels, Render, Size, StyleRefinement, Styled, View, ViewContext, WindowContext,
}; };
@ -110,7 +110,7 @@ impl Element for UniformList {
fn request_layout( fn request_layout(
&mut self, &mut self,
state: Option<Self::State>, state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
let max_items = self.item_count; let max_items = self.item_count;
let item_size = state let item_size = state
@ -158,7 +158,7 @@ impl Element for UniformList {
&mut self, &mut self,
bounds: Bounds<crate::Pixels>, bounds: Bounds<crate::Pixels>,
element_state: &mut Self::State, element_state: &mut Self::State,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
let style = let style =
self.interactivity self.interactivity
@ -280,7 +280,7 @@ impl UniformList {
self self
} }
fn measure_item(&self, list_width: Option<Pixels>, cx: &mut WindowContext) -> Size<Pixels> { fn measure_item(&self, list_width: Option<Pixels>, cx: &mut ElementContext) -> Size<Pixels> {
if self.item_count == 0 { if self.item_count == 0 {
return Size::default(); return Size::default();
} }

View file

@ -220,11 +220,6 @@ pub trait EventEmitter<E: Any>: 'static {}
/// A helper trait for auto-implementing certain methods on contexts that /// A helper trait for auto-implementing certain methods on contexts that
/// can be used interchangeably. /// can be used interchangeably.
pub trait BorrowAppContext { pub trait BorrowAppContext {
/// Run a closure with a text style pushed onto the context.
fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R
where
F: FnOnce(&mut Self) -> R;
/// Set a global value on the context. /// Set a global value on the context.
fn set_global<T: 'static>(&mut self, global: T); fn set_global<T: 'static>(&mut self, global: T);
} }
@ -233,20 +228,6 @@ impl<C> BorrowAppContext for C
where where
C: BorrowMut<AppContext>, C: BorrowMut<AppContext>,
{ {
fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R
where
F: FnOnce(&mut Self) -> R,
{
if let Some(style) = style {
self.borrow_mut().push_text_style(style);
let result = f(self);
self.borrow_mut().pop_text_style();
result
} else {
f(self)
}
}
fn set_global<G: 'static>(&mut self, global: G) { fn set_global<G: 'static>(&mut self, global: G) {
self.borrow_mut().set_global(global) self.borrow_mut().set_global(global)
} }

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
Action, ActionRegistry, DispatchPhase, EntityId, FocusId, KeyBinding, KeyContext, Keymap, Action, ActionRegistry, DispatchPhase, ElementContext, EntityId, FocusId, KeyBinding,
KeymatchResult, Keystroke, KeystrokeMatcher, WindowContext, KeyContext, Keymap, KeymatchResult, Keystroke, KeystrokeMatcher, WindowContext,
}; };
use collections::FxHashMap; use collections::FxHashMap;
use parking_lot::Mutex; use parking_lot::Mutex;
@ -36,7 +36,7 @@ pub(crate) struct DispatchNode {
parent: Option<DispatchNodeId>, parent: Option<DispatchNodeId>,
} }
type KeyListener = Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>; type KeyListener = Rc<dyn Fn(&dyn Any, DispatchPhase, &mut ElementContext)>;
#[derive(Clone)] #[derive(Clone)]
pub(crate) struct DispatchActionListener { pub(crate) struct DispatchActionListener {

View file

@ -1,10 +1,10 @@
use std::{iter, mem, ops::Range}; use std::{iter, mem, ops::Range};
use crate::{ use crate::{
black, phi, point, quad, rems, AbsoluteLength, BorrowAppContext, BorrowWindow, Bounds, black, phi, point, quad, rems, AbsoluteLength, BorrowAppContext, Bounds, ContentMask, Corners,
ContentMask, Corners, CornersRefinement, CursorStyle, DefiniteLength, Edges, EdgesRefinement, CornersRefinement, CursorStyle, DefiniteLength, Edges, EdgesRefinement, ElementContext, Font,
Font, FontFeatures, FontStyle, FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Rgba, FontFeatures, FontStyle, FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Rgba,
SharedString, Size, SizeRefinement, Styled, TextRun, WindowContext, SharedString, Size, SizeRefinement, Styled, TextRun,
}; };
use collections::HashSet; use collections::HashSet;
use refineable::{Cascade, Refineable}; use refineable::{Cascade, Refineable};
@ -308,61 +308,12 @@ impl Style {
} }
} }
pub fn apply_text_style<C, F, R>(&self, cx: &mut C, f: F) -> R
where
C: BorrowAppContext,
F: FnOnce(&mut C) -> R,
{
if self.text.is_some() {
cx.with_text_style(Some(self.text.clone()), f)
} else {
f(cx)
}
}
/// Apply overflow to content mask
pub fn apply_overflow<C, F, R>(&self, bounds: Bounds<Pixels>, cx: &mut C, f: F) -> R
where
C: BorrowWindow,
F: FnOnce(&mut C) -> R,
{
let current_mask = cx.content_mask();
let min = current_mask.bounds.origin;
let max = current_mask.bounds.lower_right();
let mask_bounds = match (
self.overflow.x == Overflow::Visible,
self.overflow.y == Overflow::Visible,
) {
// x and y both visible
(true, true) => return f(cx),
// x visible, y hidden
(true, false) => Bounds::from_corners(
point(min.x, bounds.origin.y),
point(max.x, bounds.lower_right().y),
),
// x hidden, y visible
(false, true) => Bounds::from_corners(
point(bounds.origin.x, min.y),
point(bounds.lower_right().x, max.y),
),
// both hidden
(false, false) => bounds,
};
let mask = ContentMask {
bounds: mask_bounds,
};
cx.with_content_mask(Some(mask), f)
}
/// Paints the background of an element styled with this style. /// Paints the background of an element styled with this style.
pub fn paint( pub fn paint(
&self, &self,
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
cx: &mut WindowContext, cx: &mut ElementContext,
continuation: impl FnOnce(&mut WindowContext), continuation: impl FnOnce(&mut ElementContext),
) { ) {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
if self.debug_below { if self.debug_below {

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
black, fill, point, px, size, BorrowWindow, Bounds, Hsla, LineLayout, Pixels, Point, Result, black, fill, point, px, size, Bounds, ElementContext, Hsla, LineLayout, Pixels, Point, Result,
SharedString, UnderlineStyle, WindowContext, WrapBoundary, WrappedLineLayout, SharedString, UnderlineStyle, WrapBoundary, WrappedLineLayout,
}; };
use derive_more::{Deref, DerefMut}; use derive_more::{Deref, DerefMut};
use smallvec::SmallVec; use smallvec::SmallVec;
@ -33,7 +33,7 @@ impl ShapedLine {
&self, &self,
origin: Point<Pixels>, origin: Point<Pixels>,
line_height: Pixels, line_height: Pixels,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> Result<()> { ) -> Result<()> {
paint_line( paint_line(
origin, origin,
@ -66,7 +66,7 @@ impl WrappedLine {
&self, &self,
origin: Point<Pixels>, origin: Point<Pixels>,
line_height: Pixels, line_height: Pixels,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> Result<()> { ) -> Result<()> {
paint_line( paint_line(
origin, origin,
@ -87,7 +87,7 @@ fn paint_line(
line_height: Pixels, line_height: Pixels,
decoration_runs: &[DecorationRun], decoration_runs: &[DecorationRun],
wrap_boundaries: &[WrapBoundary], wrap_boundaries: &[WrapBoundary],
cx: &mut WindowContext<'_>, cx: &mut ElementContext<'_>,
) -> Result<()> { ) -> Result<()> {
let padding_top = (line_height - layout.ascent - layout.descent) / 2.; let padding_top = (line_height - layout.ascent - layout.descent) / 2.;
let baseline_offset = point(px(0.), padding_top + layout.ascent); let baseline_offset = point(px(0.), padding_top + layout.ascent);

View file

@ -1,8 +1,8 @@
use crate::{ use crate::{
seal::Sealed, AnyElement, AnyModel, AnyWeakModel, AppContext, AvailableSpace, BorrowWindow, seal::Sealed, AnyElement, AnyModel, AnyWeakModel, AppContext, AvailableSpace, Bounds,
Bounds, ContentMask, Element, ElementId, Entity, EntityId, Flatten, FocusHandle, FocusableView, ContentMask, Element, ElementContext, ElementId, Entity, EntityId, Flatten, FocusHandle,
IntoElement, LayoutId, Model, Pixels, Point, Render, Size, StackingOrder, Style, TextStyle, FocusableView, IntoElement, LayoutId, Model, Pixels, Point, Render, Size, StackingOrder, Style,
ViewContext, VisualContext, WeakModel, WindowContext, TextStyle, ViewContext, VisualContext, WeakModel,
}; };
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use std::{ use std::{
@ -94,7 +94,7 @@ impl<V: Render> Element for View<V> {
fn request_layout( fn request_layout(
&mut self, &mut self,
_state: Option<Self::State>, _state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
cx.with_view_id(self.entity_id(), |cx| { cx.with_view_id(self.entity_id(), |cx| {
let mut element = self.update(cx, |view, cx| view.render(cx).into_any_element()); let mut element = self.update(cx, |view, cx| view.render(cx).into_any_element());
@ -103,7 +103,7 @@ impl<V: Render> Element for View<V> {
}) })
} }
fn paint(&mut self, _: Bounds<Pixels>, element: &mut Self::State, cx: &mut WindowContext) { fn paint(&mut self, _: Bounds<Pixels>, element: &mut Self::State, cx: &mut ElementContext) {
cx.paint_view(self.entity_id(), |cx| element.take().unwrap().paint(cx)); cx.paint_view(self.entity_id(), |cx| element.take().unwrap().paint(cx));
} }
} }
@ -202,7 +202,7 @@ impl<V> Eq for WeakView<V> {}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct AnyView { pub struct AnyView {
model: AnyModel, model: AnyModel,
request_layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, AnyElement), request_layout: fn(&AnyView, &mut ElementContext) -> (LayoutId, AnyElement),
cache: bool, cache: bool,
} }
@ -250,7 +250,7 @@ impl AnyView {
&self, &self,
origin: Point<Pixels>, origin: Point<Pixels>,
available_space: Size<AvailableSpace>, available_space: Size<AvailableSpace>,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
cx.paint_view(self.entity_id(), |cx| { cx.paint_view(self.entity_id(), |cx| {
cx.with_absolute_element_offset(origin, |cx| { cx.with_absolute_element_offset(origin, |cx| {
@ -278,7 +278,7 @@ impl Element for AnyView {
fn request_layout( fn request_layout(
&mut self, &mut self,
state: Option<Self::State>, state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
cx.with_view_id(self.entity_id(), |cx| { cx.with_view_id(self.entity_id(), |cx| {
if self.cache { if self.cache {
@ -299,7 +299,7 @@ impl Element for AnyView {
}) })
} }
fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) { fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut ElementContext) {
cx.paint_view(self.entity_id(), |cx| { cx.paint_view(self.entity_id(), |cx| {
if !self.cache { if !self.cache {
state.element.take().unwrap().paint(cx); state.element.take().unwrap().paint(cx);
@ -363,7 +363,7 @@ impl IntoElement for AnyView {
/// A weak, dynamically-typed view handle that does not prevent the view from being released. /// A weak, dynamically-typed view handle that does not prevent the view from being released.
pub struct AnyWeakView { pub struct AnyWeakView {
model: AnyWeakModel, model: AnyWeakModel,
layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, AnyElement), layout: fn(&AnyView, &mut ElementContext) -> (LayoutId, AnyElement),
} }
impl AnyWeakView { impl AnyWeakView {
@ -402,11 +402,11 @@ impl std::fmt::Debug for AnyWeakView {
} }
mod any_view { mod any_view {
use crate::{AnyElement, AnyView, IntoElement, LayoutId, Render, WindowContext}; use crate::{AnyElement, AnyView, ElementContext, IntoElement, LayoutId, Render};
pub(crate) fn request_layout<V: 'static + Render>( pub(crate) fn request_layout<V: 'static + Render>(
view: &AnyView, view: &AnyView,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, AnyElement) { ) -> (LayoutId, AnyElement) {
let view = view.clone().downcast::<V>().unwrap(); let view = view.clone().downcast::<V>().unwrap();
let mut element = view.update(cx, |view, cx| view.render(cx).into_any_element()); let mut element = view.update(cx, |view, cx| view.render(cx).into_any_element());

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,11 +1,11 @@
use editor::{Cursor, HighlightedRange, HighlightedRangeLine}; use editor::{Cursor, HighlightedRange, HighlightedRangeLine};
use gpui::{ use gpui::{
div, fill, point, px, relative, AnyElement, AvailableSpace, BorrowWindow, Bounds, div, fill, point, px, relative, AnyElement, AvailableSpace, Bounds, DispatchPhase, Element,
DispatchPhase, Element, ElementId, FocusHandle, Font, FontStyle, FontWeight, HighlightStyle, ElementContext, ElementId, FocusHandle, Font, FontStyle, FontWeight, HighlightStyle, Hsla,
Hsla, InputHandler, InteractiveBounds, InteractiveElement, InteractiveElementState, InputHandler, InteractiveBounds, InteractiveElement, InteractiveElementState, Interactivity,
Interactivity, IntoElement, LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton, IntoElement, LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton, MouseMoveEvent,
MouseMoveEvent, Pixels, Point, ShapedLine, StatefulInteractiveElement, Styled, TextRun, Pixels, Point, ShapedLine, StatefulInteractiveElement, Styled, TextRun, TextStyle, TextSystem,
TextStyle, TextSystem, UnderlineStyle, WeakView, WhiteSpace, WindowContext, UnderlineStyle, WeakView, WhiteSpace, WindowContext,
}; };
use itertools::Itertools; use itertools::Itertools;
use language::CursorShape; use language::CursorShape;
@ -81,7 +81,7 @@ impl LayoutCell {
origin: Point<Pixels>, origin: Point<Pixels>,
layout: &LayoutState, layout: &LayoutState,
_visible_bounds: Bounds<Pixels>, _visible_bounds: Bounds<Pixels>,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
let pos = { let pos = {
let point = self.point; let point = self.point;
@ -120,7 +120,7 @@ impl LayoutRect {
} }
} }
fn paint(&self, origin: Point<Pixels>, layout: &LayoutState, cx: &mut WindowContext) { fn paint(&self, origin: Point<Pixels>, layout: &LayoutState, cx: &mut ElementContext) {
let position = { let position = {
let alac_point = self.point; let alac_point = self.point;
point( point(
@ -365,7 +365,7 @@ impl TerminalElement {
result result
} }
fn compute_layout(&self, bounds: Bounds<gpui::Pixels>, cx: &mut WindowContext) -> LayoutState { fn compute_layout(&self, bounds: Bounds<gpui::Pixels>, cx: &mut ElementContext) -> LayoutState {
let settings = ThemeSettings::get_global(cx).clone(); let settings = ThemeSettings::get_global(cx).clone();
let buffer_font_size = settings.buffer_font_size(cx); let buffer_font_size = settings.buffer_font_size(cx);
@ -590,7 +590,7 @@ impl TerminalElement {
origin: Point<Pixels>, origin: Point<Pixels>,
mode: TermMode, mode: TermMode,
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
let focus = self.focus.clone(); let focus = self.focus.clone();
let terminal = self.terminal.clone(); let terminal = self.terminal.clone();
@ -722,7 +722,7 @@ impl Element for TerminalElement {
fn request_layout( fn request_layout(
&mut self, &mut self,
element_state: Option<Self::State>, element_state: Option<Self::State>,
cx: &mut WindowContext<'_>, cx: &mut ElementContext<'_>,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
let (layout_id, interactive_state) = let (layout_id, interactive_state) =
self.interactivity self.interactivity
@ -741,7 +741,7 @@ impl Element for TerminalElement {
&mut self, &mut self,
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
state: &mut Self::State, state: &mut Self::State,
cx: &mut WindowContext<'_>, cx: &mut ElementContext<'_>,
) { ) {
let mut layout = self.compute_layout(bounds, cx); let mut layout = self.compute_layout(bounds, cx);

View file

@ -2,8 +2,9 @@ use std::{cell::RefCell, rc::Rc};
use gpui::{ use gpui::{
overlay, point, prelude::FluentBuilder, px, rems, AnchorCorner, AnyElement, Bounds, overlay, point, prelude::FluentBuilder, px, rems, AnchorCorner, AnyElement, Bounds,
DismissEvent, DispatchPhase, Element, ElementId, InteractiveBounds, IntoElement, LayoutId, DismissEvent, DispatchPhase, Element, ElementContext, ElementId, InteractiveBounds,
ManagedView, MouseDownEvent, ParentElement, Pixels, Point, View, VisualContext, WindowContext, IntoElement, LayoutId, ManagedView, MouseDownEvent, ParentElement, Pixels, Point, View,
VisualContext, WindowContext,
}; };
use crate::{Clickable, Selectable}; use crate::{Clickable, Selectable};
@ -134,7 +135,7 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
fn request_layout( fn request_layout(
&mut self, &mut self,
element_state: Option<Self::State>, element_state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (gpui::LayoutId, Self::State) { ) -> (gpui::LayoutId, Self::State) {
let mut menu_layout_id = None; let mut menu_layout_id = None;
@ -188,7 +189,7 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
&mut self, &mut self,
_: Bounds<gpui::Pixels>, _: Bounds<gpui::Pixels>,
element_state: &mut Self::State, element_state: &mut Self::State,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
if let Some(mut child) = element_state.child_element.take() { if let Some(mut child) = element_state.child_element.take() {
child.paint(cx); child.paint(cx);

View file

@ -1,9 +1,9 @@
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, rc::Rc};
use gpui::{ use gpui::{
overlay, AnchorCorner, AnyElement, BorrowWindow, Bounds, DismissEvent, DispatchPhase, Element, overlay, AnchorCorner, AnyElement, Bounds, DismissEvent, DispatchPhase, Element,
ElementId, InteractiveBounds, IntoElement, LayoutId, ManagedView, MouseButton, MouseDownEvent, ElementContext, ElementId, InteractiveBounds, IntoElement, LayoutId, ManagedView, MouseButton,
ParentElement, Pixels, Point, View, VisualContext, WindowContext, MouseDownEvent, ParentElement, Pixels, Point, View, VisualContext, WindowContext,
}; };
pub struct RightClickMenu<M: ManagedView> { pub struct RightClickMenu<M: ManagedView> {
@ -64,7 +64,7 @@ impl<M: ManagedView> Element for RightClickMenu<M> {
fn request_layout( fn request_layout(
&mut self, &mut self,
element_state: Option<Self::State>, element_state: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (gpui::LayoutId, Self::State) { ) -> (gpui::LayoutId, Self::State) {
let (menu, position) = if let Some(element_state) = element_state { let (menu, position) = if let Some(element_state) = element_state {
(element_state.menu, element_state.position) (element_state.menu, element_state.position)
@ -116,7 +116,7 @@ impl<M: ManagedView> Element for RightClickMenu<M> {
&mut self, &mut self,
bounds: Bounds<gpui::Pixels>, bounds: Bounds<gpui::Pixels>,
element_state: &mut Self::State, element_state: &mut Self::State,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
if let Some(mut child) = element_state.child_element.take() { if let Some(mut child) = element_state.child_element.take() {
child.paint(cx); child.paint(cx);

View file

@ -2,9 +2,9 @@
pub use gpui::prelude::*; pub use gpui::prelude::*;
pub use gpui::{ pub use gpui::{
div, px, relative, rems, AbsoluteLength, DefiniteLength, Div, Element, ElementId, div, px, relative, rems, AbsoluteLength, DefiniteLength, Div, Element, ElementContext,
InteractiveElement, ParentElement, Pixels, Rems, RenderOnce, SharedString, Styled, ViewContext, ElementId, InteractiveElement, ParentElement, Pixels, Rems, RenderOnce, SharedString, Styled,
WindowContext, ViewContext, WindowContext,
}; };
pub use crate::clickable::*; pub use crate::clickable::*;

View file

@ -7,7 +7,7 @@ use std::time::Duration;
use command_palette::CommandPalette; use command_palette::CommandPalette;
use editor::DisplayPoint; use editor::DisplayPoint;
use gpui::{Action, KeyBinding}; use gpui::KeyBinding;
pub use neovim_backed_binding_test_context::*; pub use neovim_backed_binding_test_context::*;
pub use neovim_backed_test_context::*; pub use neovim_backed_test_context::*;
pub use vim_test_context::*; pub use vim_test_context::*;
@ -15,7 +15,7 @@ pub use vim_test_context::*;
use indoc::indoc; use indoc::indoc;
use search::BufferSearchBar; use search::BufferSearchBar;
use crate::{insert::NormalBefore, motion, normal::InsertLineBelow, state::Mode, ModeIndicator}; use crate::{insert::NormalBefore, motion, state::Mode, ModeIndicator};
#[gpui::test] #[gpui::test]
async fn test_initially_disabled(cx: &mut gpui::TestAppContext) { async fn test_initially_disabled(cx: &mut gpui::TestAppContext) {

View file

@ -710,7 +710,7 @@ mod element {
pane_bounds: Bounds<Pixels>, pane_bounds: Bounds<Pixels>,
axis_bounds: Bounds<Pixels>, axis_bounds: Bounds<Pixels>,
workspace: WeakView<Workspace>, workspace: WeakView<Workspace>,
cx: &mut WindowContext, cx: &mut ElementContext,
) { ) {
let handle_bounds = Bounds { let handle_bounds = Bounds {
origin: pane_bounds.origin.apply_along(axis, |origin| { origin: pane_bounds.origin.apply_along(axis, |origin| {
@ -803,7 +803,7 @@ mod element {
fn request_layout( fn request_layout(
&mut self, &mut self,
state: Option<Self::State>, state: Option<Self::State>,
cx: &mut ui::prelude::WindowContext, cx: &mut ui::prelude::ElementContext,
) -> (gpui::LayoutId, Self::State) { ) -> (gpui::LayoutId, Self::State) {
let mut style = Style::default(); let mut style = Style::default();
style.flex_grow = 1.; style.flex_grow = 1.;
@ -820,7 +820,7 @@ mod element {
&mut self, &mut self,
bounds: gpui::Bounds<ui::prelude::Pixels>, bounds: gpui::Bounds<ui::prelude::Pixels>,
state: &mut Self::State, state: &mut Self::State,
cx: &mut ui::prelude::WindowContext, cx: &mut ui::prelude::ElementContext,
) { ) {
let flexes = self.flexes.lock().clone(); let flexes = self.flexes.lock().clone();
let len = self.children.len(); let len = self.children.len();

View file

@ -26,12 +26,12 @@ use futures::{
}; };
use gpui::{ use gpui::{
actions, canvas, div, impl_actions, point, px, size, Action, AnyElement, AnyModel, AnyView, actions, canvas, div, impl_actions, point, px, size, Action, AnyElement, AnyModel, AnyView,
AnyWeakView, AppContext, AsyncAppContext, AsyncWindowContext, BorrowWindow, Bounds, Context, AnyWeakView, AppContext, AsyncAppContext, AsyncWindowContext, Bounds, Context, Div,
Div, DragMoveEvent, Element, Entity, EntityId, EventEmitter, FocusHandle, FocusableView, DragMoveEvent, Element, ElementContext, Entity, EntityId, EventEmitter, FocusHandle,
GlobalPixels, InteractiveElement, IntoElement, KeyContext, LayoutId, ManagedView, Model, FocusableView, GlobalPixels, InteractiveElement, IntoElement, KeyContext, LayoutId,
ModelContext, ParentElement, PathPromptOptions, Pixels, Point, PromptLevel, Render, Size, ManagedView, Model, ModelContext, ParentElement, PathPromptOptions, Pixels, Point, PromptLevel,
Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowBounds, Render, Size, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView,
WindowContext, WindowHandle, WindowOptions, WindowBounds, WindowContext, WindowHandle, WindowOptions,
}; };
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem}; use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
use itertools::Itertools; use itertools::Itertools;
@ -3539,9 +3539,14 @@ impl Render for Workspace {
.border_b() .border_b()
.border_color(colors.border) .border_color(colors.border)
.child( .child(
canvas(cx.listener(|workspace, bounds, _| { canvas({
workspace.bounds = *bounds; let this = cx.view().clone();
})) move |bounds, cx| {
this.update(cx, |this, _cx| {
this.bounds = *bounds;
})
}
})
.absolute() .absolute()
.size_full(), .size_full(),
) )
@ -4293,7 +4298,7 @@ impl Element for DisconnectedOverlay {
fn request_layout( fn request_layout(
&mut self, &mut self,
_: Option<Self::State>, _: Option<Self::State>,
cx: &mut WindowContext, cx: &mut ElementContext,
) -> (LayoutId, Self::State) { ) -> (LayoutId, Self::State) {
let mut background = cx.theme().colors().elevated_surface_background; let mut background = cx.theme().colors().elevated_surface_background;
background.fade_out(0.2); background.fade_out(0.2);
@ -4315,7 +4320,12 @@ impl Element for DisconnectedOverlay {
(overlay.request_layout(cx), overlay) (overlay.request_layout(cx), overlay)
} }
fn paint(&mut self, bounds: Bounds<Pixels>, overlay: &mut Self::State, cx: &mut WindowContext) { fn paint(
&mut self,
bounds: Bounds<Pixels>,
overlay: &mut Self::State,
cx: &mut ElementContext,
) {
cx.with_z_index(u8::MAX, |cx| { cx.with_z_index(u8::MAX, |cx| {
cx.add_opaque_layer(bounds); cx.add_opaque_layer(bounds);
overlay.paint(cx); overlay.paint(cx);