1//! The element context is the main interface for interacting with the frame during a paint.
2//!
3//! Elements are hierarchical and with a few exceptions the context accumulates state in a stack
4//! as it processes all of the elements in the frame. The methods that interact with this stack
5//! are generally marked with `with_*`, and take a callback to denote the region of code that
6//! should be executed with that state.
7//!
8//! The other main interface is the `paint_*` family of methods, which push basic drawing commands
9//! to the GPU. Everything in a GPUI app is drawn with these methods.
10//!
11//! There are also several internal methods that GPUI uses, such as [`ElementContext::with_element_state`]
12//! to call the paint and layout methods on elements. These have been included as they're often useful
13//! for taking manual control of the layouting or painting of specialized elements.
14
15use std::{
16 any::{Any, TypeId},
17 borrow::{Borrow, BorrowMut, Cow},
18 cmp, mem,
19 ops::Range,
20 rc::Rc,
21 sync::Arc,
22};
23
24use anyhow::Result;
25use collections::FxHashMap;
26use derive_more::{Deref, DerefMut};
27use futures::{future::Shared, FutureExt};
28#[cfg(target_os = "macos")]
29use media::core_video::CVImageBuffer;
30use smallvec::SmallVec;
31use util::post_inc;
32
33use crate::{
34 hash, point, prelude::*, px, size, AnyElement, AnyTooltip, AppContext, Asset, AvailableSpace,
35 Bounds, BoxShadow, ContentMask, Corners, CursorStyle, DevicePixels, DispatchNodeId,
36 DispatchPhase, DispatchTree, DrawPhase, ElementId, ElementStateBox, EntityId, FocusHandle,
37 FocusId, FontId, GlobalElementId, GlyphId, Hsla, ImageData, InputHandler, IsZero, KeyContext,
38 KeyEvent, LayoutId, LineLayoutIndex, ModifiersChangedEvent, MonochromeSprite, MouseEvent,
39 PaintQuad, Path, Pixels, PlatformInputHandler, Point, PolychromeSprite, Quad,
40 RenderGlyphParams, RenderImageParams, RenderSvgParams, Scene, Shadow, SharedString, Size,
41 StrikethroughStyle, Style, Task, TextStyleRefinement, TransformationMatrix, Underline,
42 UnderlineStyle, Window, WindowContext, SUBPIXEL_VARIANTS,
43};
44
45pub(crate) type AnyMouseListener =
46 Box<dyn FnMut(&dyn Any, DispatchPhase, &mut ElementContext) + 'static>;
47
48#[derive(Clone)]
49pub(crate) struct CursorStyleRequest {
50 pub(crate) hitbox_id: HitboxId,
51 pub(crate) style: CursorStyle,
52}
53
54/// An identifier for a [Hitbox].
55#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
56pub struct HitboxId(usize);
57
58impl HitboxId {
59 /// Checks if the hitbox with this id is currently hovered.
60 pub fn is_hovered(&self, cx: &WindowContext) -> bool {
61 cx.window.mouse_hit_test.0.contains(self)
62 }
63}
64
65/// A rectangular region that potentially blocks hitboxes inserted prior.
66/// See [ElementContext::insert_hitbox] for more details.
67#[derive(Clone, Debug, Deref)]
68pub struct Hitbox {
69 /// A unique identifier for the hitbox.
70 pub id: HitboxId,
71 /// The bounds of the hitbox.
72 #[deref]
73 pub bounds: Bounds<Pixels>,
74 /// The content mask when the hitbox was inserted.
75 pub content_mask: ContentMask<Pixels>,
76 /// Whether the hitbox occludes other hitboxes inserted prior.
77 pub opaque: bool,
78}
79
80impl Hitbox {
81 /// Checks if the hitbox is currently hovered.
82 pub fn is_hovered(&self, cx: &WindowContext) -> bool {
83 self.id.is_hovered(cx)
84 }
85}
86
87#[derive(Default, Eq, PartialEq)]
88pub(crate) struct HitTest(SmallVec<[HitboxId; 8]>);
89
90/// An identifier for a tooltip.
91#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
92pub struct TooltipId(usize);
93
94impl TooltipId {
95 /// Checks if the tooltip is currently hovered.
96 pub fn is_hovered(&self, cx: &WindowContext) -> bool {
97 cx.window
98 .tooltip_bounds
99 .as_ref()
100 .map_or(false, |tooltip_bounds| {
101 tooltip_bounds.id == *self && tooltip_bounds.bounds.contains(&cx.mouse_position())
102 })
103 }
104}
105
106pub(crate) struct TooltipBounds {
107 id: TooltipId,
108 bounds: Bounds<Pixels>,
109}
110
111#[derive(Clone)]
112pub(crate) struct TooltipRequest {
113 id: TooltipId,
114 tooltip: AnyTooltip,
115}
116
117pub(crate) struct DeferredDraw {
118 priority: usize,
119 parent_node: DispatchNodeId,
120 element_id_stack: GlobalElementId,
121 text_style_stack: Vec<TextStyleRefinement>,
122 element: Option<AnyElement>,
123 absolute_offset: Point<Pixels>,
124 layout_range: Range<AfterLayoutIndex>,
125 paint_range: Range<PaintIndex>,
126}
127
128pub(crate) struct Frame {
129 pub(crate) focus: Option<FocusId>,
130 pub(crate) window_active: bool,
131 pub(crate) element_states: FxHashMap<(GlobalElementId, TypeId), ElementStateBox>,
132 accessed_element_states: Vec<(GlobalElementId, TypeId)>,
133 pub(crate) mouse_listeners: Vec<Option<AnyMouseListener>>,
134 pub(crate) dispatch_tree: DispatchTree,
135 pub(crate) scene: Scene,
136 pub(crate) hitboxes: Vec<Hitbox>,
137 pub(crate) deferred_draws: Vec<DeferredDraw>,
138 pub(crate) content_mask_stack: Vec<ContentMask<Pixels>>,
139 pub(crate) element_offset_stack: Vec<Point<Pixels>>,
140 pub(crate) input_handlers: Vec<Option<PlatformInputHandler>>,
141 pub(crate) tooltip_requests: Vec<Option<TooltipRequest>>,
142 pub(crate) cursor_styles: Vec<CursorStyleRequest>,
143 #[cfg(any(test, feature = "test-support"))]
144 pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>,
145}
146
147#[derive(Clone, Default)]
148pub(crate) struct AfterLayoutIndex {
149 hitboxes_index: usize,
150 tooltips_index: usize,
151 deferred_draws_index: usize,
152 dispatch_tree_index: usize,
153 accessed_element_states_index: usize,
154 line_layout_index: LineLayoutIndex,
155}
156
157#[derive(Clone, Default)]
158pub(crate) struct PaintIndex {
159 scene_index: usize,
160 mouse_listeners_index: usize,
161 input_handlers_index: usize,
162 cursor_styles_index: usize,
163 accessed_element_states_index: usize,
164 line_layout_index: LineLayoutIndex,
165}
166
167impl Frame {
168 pub(crate) fn new(dispatch_tree: DispatchTree) -> Self {
169 Frame {
170 focus: None,
171 window_active: false,
172 element_states: FxHashMap::default(),
173 accessed_element_states: Vec::new(),
174 mouse_listeners: Vec::new(),
175 dispatch_tree,
176 scene: Scene::default(),
177 hitboxes: Vec::new(),
178 deferred_draws: Vec::new(),
179 content_mask_stack: Vec::new(),
180 element_offset_stack: Vec::new(),
181 input_handlers: Vec::new(),
182 tooltip_requests: Vec::new(),
183 cursor_styles: Vec::new(),
184
185 #[cfg(any(test, feature = "test-support"))]
186 debug_bounds: FxHashMap::default(),
187 }
188 }
189
190 pub(crate) fn clear(&mut self) {
191 self.element_states.clear();
192 self.accessed_element_states.clear();
193 self.mouse_listeners.clear();
194 self.dispatch_tree.clear();
195 self.scene.clear();
196 self.input_handlers.clear();
197 self.tooltip_requests.clear();
198 self.cursor_styles.clear();
199 self.hitboxes.clear();
200 self.deferred_draws.clear();
201 }
202
203 pub(crate) fn hit_test(&self, position: Point<Pixels>) -> HitTest {
204 let mut hit_test = HitTest::default();
205 for hitbox in self.hitboxes.iter().rev() {
206 let bounds = hitbox.bounds.intersect(&hitbox.content_mask.bounds);
207 if bounds.contains(&position) {
208 hit_test.0.push(hitbox.id);
209 if hitbox.opaque {
210 break;
211 }
212 }
213 }
214 hit_test
215 }
216
217 pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> {
218 self.focus
219 .map(|focus_id| self.dispatch_tree.focus_path(focus_id))
220 .unwrap_or_default()
221 }
222
223 pub(crate) fn finish(&mut self, prev_frame: &mut Self) {
224 for element_state_key in &self.accessed_element_states {
225 if let Some(element_state) = prev_frame.element_states.remove(element_state_key) {
226 self.element_states
227 .insert(element_state_key.clone(), element_state);
228 }
229 }
230
231 self.scene.finish();
232 }
233}
234
235/// This context is used for assisting in the implementation of the element trait
236#[derive(Deref, DerefMut)]
237pub struct ElementContext<'a> {
238 pub(crate) cx: WindowContext<'a>,
239}
240
241impl<'a> WindowContext<'a> {
242 /// Convert this window context into an ElementContext in this callback.
243 /// If you need to use this method, you're probably intermixing the imperative
244 /// and declarative APIs, which is not recommended.
245 pub fn with_element_context<R>(&mut self, f: impl FnOnce(&mut ElementContext) -> R) -> R {
246 f(&mut ElementContext {
247 cx: WindowContext::new(self.app, self.window),
248 })
249 }
250}
251
252impl<'a> Borrow<AppContext> for ElementContext<'a> {
253 fn borrow(&self) -> &AppContext {
254 self.cx.app
255 }
256}
257
258impl<'a> BorrowMut<AppContext> for ElementContext<'a> {
259 fn borrow_mut(&mut self) -> &mut AppContext {
260 self.cx.borrow_mut()
261 }
262}
263
264impl<'a> Borrow<WindowContext<'a>> for ElementContext<'a> {
265 fn borrow(&self) -> &WindowContext<'a> {
266 &self.cx
267 }
268}
269
270impl<'a> BorrowMut<WindowContext<'a>> for ElementContext<'a> {
271 fn borrow_mut(&mut self) -> &mut WindowContext<'a> {
272 &mut self.cx
273 }
274}
275
276impl<'a> Borrow<Window> for ElementContext<'a> {
277 fn borrow(&self) -> &Window {
278 self.cx.window
279 }
280}
281
282impl<'a> BorrowMut<Window> for ElementContext<'a> {
283 fn borrow_mut(&mut self) -> &mut Window {
284 self.cx.borrow_mut()
285 }
286}
287
288impl<'a> Context for ElementContext<'a> {
289 type Result<T> = <WindowContext<'a> as Context>::Result<T>;
290
291 fn new_model<T: 'static>(
292 &mut self,
293 build_model: impl FnOnce(&mut crate::ModelContext<'_, T>) -> T,
294 ) -> Self::Result<crate::Model<T>> {
295 self.cx.new_model(build_model)
296 }
297
298 fn reserve_model<T: 'static>(&mut self) -> Self::Result<crate::Reservation<T>> {
299 self.cx.reserve_model()
300 }
301
302 fn insert_model<T: 'static>(
303 &mut self,
304 reservation: crate::Reservation<T>,
305 build_model: impl FnOnce(&mut crate::ModelContext<'_, T>) -> T,
306 ) -> Self::Result<crate::Model<T>> {
307 self.cx.insert_model(reservation, build_model)
308 }
309
310 fn update_model<T, R>(
311 &mut self,
312 handle: &crate::Model<T>,
313 update: impl FnOnce(&mut T, &mut crate::ModelContext<'_, T>) -> R,
314 ) -> Self::Result<R>
315 where
316 T: 'static,
317 {
318 self.cx.update_model(handle, update)
319 }
320
321 fn read_model<T, R>(
322 &self,
323 handle: &crate::Model<T>,
324 read: impl FnOnce(&T, &AppContext) -> R,
325 ) -> Self::Result<R>
326 where
327 T: 'static,
328 {
329 self.cx.read_model(handle, read)
330 }
331
332 fn update_window<T, F>(&mut self, window: crate::AnyWindowHandle, f: F) -> Result<T>
333 where
334 F: FnOnce(crate::AnyView, &mut WindowContext<'_>) -> T,
335 {
336 self.cx.update_window(window, f)
337 }
338
339 fn read_window<T, R>(
340 &self,
341 window: &crate::WindowHandle<T>,
342 read: impl FnOnce(crate::View<T>, &AppContext) -> R,
343 ) -> Result<R>
344 where
345 T: 'static,
346 {
347 self.cx.read_window(window, read)
348 }
349}
350
351impl<'a> VisualContext for ElementContext<'a> {
352 fn new_view<V>(
353 &mut self,
354 build_view: impl FnOnce(&mut crate::ViewContext<'_, V>) -> V,
355 ) -> Self::Result<crate::View<V>>
356 where
357 V: 'static + Render,
358 {
359 self.cx.new_view(build_view)
360 }
361
362 fn update_view<V: 'static, R>(
363 &mut self,
364 view: &crate::View<V>,
365 update: impl FnOnce(&mut V, &mut crate::ViewContext<'_, V>) -> R,
366 ) -> Self::Result<R> {
367 self.cx.update_view(view, update)
368 }
369
370 fn replace_root_view<V>(
371 &mut self,
372 build_view: impl FnOnce(&mut crate::ViewContext<'_, V>) -> V,
373 ) -> Self::Result<crate::View<V>>
374 where
375 V: 'static + Render,
376 {
377 self.cx.replace_root_view(build_view)
378 }
379
380 fn focus_view<V>(&mut self, view: &crate::View<V>) -> Self::Result<()>
381 where
382 V: crate::FocusableView,
383 {
384 self.cx.focus_view(view)
385 }
386
387 fn dismiss_view<V>(&mut self, view: &crate::View<V>) -> Self::Result<()>
388 where
389 V: crate::ManagedView,
390 {
391 self.cx.dismiss_view(view)
392 }
393}
394
395impl<'a> ElementContext<'a> {
396 pub(crate) fn draw_roots(&mut self) {
397 self.window.draw_phase = DrawPhase::Layout;
398 self.window.tooltip_bounds.take();
399
400 // Layout all root elements.
401 let mut root_element = self.window.root_view.as_ref().unwrap().clone().into_any();
402 root_element.layout(Point::default(), self.window.viewport_size.into(), self);
403
404 let mut sorted_deferred_draws =
405 (0..self.window.next_frame.deferred_draws.len()).collect::<SmallVec<[_; 8]>>();
406 sorted_deferred_draws.sort_by_key(|ix| self.window.next_frame.deferred_draws[*ix].priority);
407 self.layout_deferred_draws(&sorted_deferred_draws);
408
409 let mut prompt_element = None;
410 let mut active_drag_element = None;
411 let mut tooltip_element = None;
412 if let Some(prompt) = self.window.prompt.take() {
413 let mut element = prompt.view.any_view().into_any();
414 element.layout(Point::default(), self.window.viewport_size.into(), self);
415 prompt_element = Some(element);
416 self.window.prompt = Some(prompt);
417 } else if let Some(active_drag) = self.app.active_drag.take() {
418 let mut element = active_drag.view.clone().into_any();
419 let offset = self.mouse_position() - active_drag.cursor_offset;
420 element.layout(offset, AvailableSpace::min_size(), self);
421 active_drag_element = Some(element);
422 self.app.active_drag = Some(active_drag);
423 } else {
424 tooltip_element = self.layout_tooltip();
425 }
426
427 self.window.mouse_hit_test = self.window.next_frame.hit_test(self.window.mouse_position);
428
429 // Now actually paint the elements.
430 self.window.draw_phase = DrawPhase::Paint;
431 root_element.paint(self);
432
433 self.paint_deferred_draws(&sorted_deferred_draws);
434
435 if let Some(mut prompt_element) = prompt_element {
436 prompt_element.paint(self)
437 } else if let Some(mut drag_element) = active_drag_element {
438 drag_element.paint(self);
439 } else if let Some(mut tooltip_element) = tooltip_element {
440 tooltip_element.paint(self);
441 }
442 }
443
444 fn layout_tooltip(&mut self) -> Option<AnyElement> {
445 let tooltip_request = self.window.next_frame.tooltip_requests.last().cloned()?;
446 let tooltip_request = tooltip_request.unwrap();
447 let mut element = tooltip_request.tooltip.view.clone().into_any();
448 let mouse_position = tooltip_request.tooltip.mouse_position;
449 let tooltip_size = element.measure(AvailableSpace::min_size(), self);
450
451 let mut tooltip_bounds = Bounds::new(mouse_position + point(px(1.), px(1.)), tooltip_size);
452 let window_bounds = Bounds {
453 origin: Point::default(),
454 size: self.viewport_size(),
455 };
456
457 if tooltip_bounds.right() > window_bounds.right() {
458 let new_x = mouse_position.x - tooltip_bounds.size.width - px(1.);
459 if new_x >= Pixels::ZERO {
460 tooltip_bounds.origin.x = new_x;
461 } else {
462 tooltip_bounds.origin.x = cmp::max(
463 Pixels::ZERO,
464 tooltip_bounds.origin.x - tooltip_bounds.right() - window_bounds.right(),
465 );
466 }
467 }
468
469 if tooltip_bounds.bottom() > window_bounds.bottom() {
470 let new_y = mouse_position.y - tooltip_bounds.size.height - px(1.);
471 if new_y >= Pixels::ZERO {
472 tooltip_bounds.origin.y = new_y;
473 } else {
474 tooltip_bounds.origin.y = cmp::max(
475 Pixels::ZERO,
476 tooltip_bounds.origin.y - tooltip_bounds.bottom() - window_bounds.bottom(),
477 );
478 }
479 }
480
481 self.with_absolute_element_offset(tooltip_bounds.origin, |cx| element.after_layout(cx));
482
483 self.window.tooltip_bounds = Some(TooltipBounds {
484 id: tooltip_request.id,
485 bounds: tooltip_bounds,
486 });
487 Some(element)
488 }
489
490 fn layout_deferred_draws(&mut self, deferred_draw_indices: &[usize]) {
491 assert_eq!(self.window.element_id_stack.len(), 0);
492
493 let mut deferred_draws = mem::take(&mut self.window.next_frame.deferred_draws);
494 for deferred_draw_ix in deferred_draw_indices {
495 let deferred_draw = &mut deferred_draws[*deferred_draw_ix];
496 self.window.element_id_stack = deferred_draw.element_id_stack.clone();
497 self.window.text_style_stack = deferred_draw.text_style_stack.clone();
498 self.window
499 .next_frame
500 .dispatch_tree
501 .set_active_node(deferred_draw.parent_node);
502
503 let layout_start = self.after_layout_index();
504 if let Some(element) = deferred_draw.element.as_mut() {
505 self.with_absolute_element_offset(deferred_draw.absolute_offset, |cx| {
506 element.after_layout(cx)
507 });
508 } else {
509 self.reuse_after_layout(deferred_draw.layout_range.clone());
510 }
511 let layout_end = self.after_layout_index();
512 deferred_draw.layout_range = layout_start..layout_end;
513 }
514 assert_eq!(
515 self.window.next_frame.deferred_draws.len(),
516 0,
517 "cannot call defer_draw during deferred drawing"
518 );
519 self.window.next_frame.deferred_draws = deferred_draws;
520 self.window.element_id_stack.clear();
521 self.window.text_style_stack.clear();
522 }
523
524 fn paint_deferred_draws(&mut self, deferred_draw_indices: &[usize]) {
525 assert_eq!(self.window.element_id_stack.len(), 0);
526
527 let mut deferred_draws = mem::take(&mut self.window.next_frame.deferred_draws);
528 for deferred_draw_ix in deferred_draw_indices {
529 let mut deferred_draw = &mut deferred_draws[*deferred_draw_ix];
530 self.window.element_id_stack = deferred_draw.element_id_stack.clone();
531 self.window
532 .next_frame
533 .dispatch_tree
534 .set_active_node(deferred_draw.parent_node);
535
536 let paint_start = self.paint_index();
537 if let Some(element) = deferred_draw.element.as_mut() {
538 element.paint(self);
539 } else {
540 self.reuse_paint(deferred_draw.paint_range.clone());
541 }
542 let paint_end = self.paint_index();
543 deferred_draw.paint_range = paint_start..paint_end;
544 }
545 self.window.next_frame.deferred_draws = deferred_draws;
546 self.window.element_id_stack.clear();
547 }
548
549 pub(crate) fn after_layout_index(&self) -> AfterLayoutIndex {
550 AfterLayoutIndex {
551 hitboxes_index: self.window.next_frame.hitboxes.len(),
552 tooltips_index: self.window.next_frame.tooltip_requests.len(),
553 deferred_draws_index: self.window.next_frame.deferred_draws.len(),
554 dispatch_tree_index: self.window.next_frame.dispatch_tree.len(),
555 accessed_element_states_index: self.window.next_frame.accessed_element_states.len(),
556 line_layout_index: self.window.text_system.layout_index(),
557 }
558 }
559
560 pub(crate) fn reuse_after_layout(&mut self, range: Range<AfterLayoutIndex>) {
561 let window = &mut self.window;
562 window.next_frame.hitboxes.extend(
563 window.rendered_frame.hitboxes[range.start.hitboxes_index..range.end.hitboxes_index]
564 .iter()
565 .cloned(),
566 );
567 window.next_frame.tooltip_requests.extend(
568 window.rendered_frame.tooltip_requests
569 [range.start.tooltips_index..range.end.tooltips_index]
570 .iter_mut()
571 .map(|request| request.take()),
572 );
573 window.next_frame.accessed_element_states.extend(
574 window.rendered_frame.accessed_element_states[range.start.accessed_element_states_index
575 ..range.end.accessed_element_states_index]
576 .iter()
577 .cloned(),
578 );
579 window
580 .text_system
581 .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);
582
583 let reused_subtree = window.next_frame.dispatch_tree.reuse_subtree(
584 range.start.dispatch_tree_index..range.end.dispatch_tree_index,
585 &mut window.rendered_frame.dispatch_tree,
586 );
587 window.next_frame.deferred_draws.extend(
588 window.rendered_frame.deferred_draws
589 [range.start.deferred_draws_index..range.end.deferred_draws_index]
590 .iter()
591 .map(|deferred_draw| DeferredDraw {
592 parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node),
593 element_id_stack: deferred_draw.element_id_stack.clone(),
594 text_style_stack: deferred_draw.text_style_stack.clone(),
595 priority: deferred_draw.priority,
596 element: None,
597 absolute_offset: deferred_draw.absolute_offset,
598 layout_range: deferred_draw.layout_range.clone(),
599 paint_range: deferred_draw.paint_range.clone(),
600 }),
601 );
602 }
603
604 pub(crate) fn paint_index(&self) -> PaintIndex {
605 PaintIndex {
606 scene_index: self.window.next_frame.scene.len(),
607 mouse_listeners_index: self.window.next_frame.mouse_listeners.len(),
608 input_handlers_index: self.window.next_frame.input_handlers.len(),
609 cursor_styles_index: self.window.next_frame.cursor_styles.len(),
610 accessed_element_states_index: self.window.next_frame.accessed_element_states.len(),
611 line_layout_index: self.window.text_system.layout_index(),
612 }
613 }
614
615 pub(crate) fn reuse_paint(&mut self, range: Range<PaintIndex>) {
616 let window = &mut self.cx.window;
617
618 window.next_frame.cursor_styles.extend(
619 window.rendered_frame.cursor_styles
620 [range.start.cursor_styles_index..range.end.cursor_styles_index]
621 .iter()
622 .cloned(),
623 );
624 window.next_frame.input_handlers.extend(
625 window.rendered_frame.input_handlers
626 [range.start.input_handlers_index..range.end.input_handlers_index]
627 .iter_mut()
628 .map(|handler| handler.take()),
629 );
630 window.next_frame.mouse_listeners.extend(
631 window.rendered_frame.mouse_listeners
632 [range.start.mouse_listeners_index..range.end.mouse_listeners_index]
633 .iter_mut()
634 .map(|listener| listener.take()),
635 );
636 window.next_frame.accessed_element_states.extend(
637 window.rendered_frame.accessed_element_states[range.start.accessed_element_states_index
638 ..range.end.accessed_element_states_index]
639 .iter()
640 .cloned(),
641 );
642 window
643 .text_system
644 .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);
645 window.next_frame.scene.replay(
646 range.start.scene_index..range.end.scene_index,
647 &window.rendered_frame.scene,
648 );
649 }
650
651 /// Push a text style onto the stack, and call a function with that style active.
652 /// Use [`AppContext::text_style`] to get the current, combined text style.
653 pub fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R
654 where
655 F: FnOnce(&mut Self) -> R,
656 {
657 if let Some(style) = style {
658 self.window.text_style_stack.push(style);
659 let result = f(self);
660 self.window.text_style_stack.pop();
661 result
662 } else {
663 f(self)
664 }
665 }
666
667 /// Updates the cursor style at the platform level.
668 pub fn set_cursor_style(&mut self, style: CursorStyle, hitbox: &Hitbox) {
669 self.window
670 .next_frame
671 .cursor_styles
672 .push(CursorStyleRequest {
673 hitbox_id: hitbox.id,
674 style,
675 });
676 }
677
678 /// Sets a tooltip to be rendered for the upcoming frame
679 pub fn set_tooltip(&mut self, tooltip: AnyTooltip) -> TooltipId {
680 let id = TooltipId(post_inc(&mut self.window.next_tooltip_id.0));
681 self.window
682 .next_frame
683 .tooltip_requests
684 .push(Some(TooltipRequest { id, tooltip }));
685 id
686 }
687
688 /// Pushes the given element id onto the global stack and invokes the given closure
689 /// with a `GlobalElementId`, which disambiguates the given id in the context of its ancestor
690 /// ids. Because elements are discarded and recreated on each frame, the `GlobalElementId` is
691 /// used to associate state with identified elements across separate frames.
692 pub fn with_element_id<R>(
693 &mut self,
694 id: Option<impl Into<ElementId>>,
695 f: impl FnOnce(&mut Self) -> R,
696 ) -> R {
697 if let Some(id) = id.map(Into::into) {
698 let window = self.window_mut();
699 window.element_id_stack.push(id);
700 let result = f(self);
701 let window: &mut Window = self.borrow_mut();
702 window.element_id_stack.pop();
703 result
704 } else {
705 f(self)
706 }
707 }
708
709 /// Invoke the given function with the given content mask after intersecting it
710 /// with the current mask.
711 pub fn with_content_mask<R>(
712 &mut self,
713 mask: Option<ContentMask<Pixels>>,
714 f: impl FnOnce(&mut Self) -> R,
715 ) -> R {
716 if let Some(mask) = mask {
717 let mask = mask.intersect(&self.content_mask());
718 self.window_mut().next_frame.content_mask_stack.push(mask);
719 let result = f(self);
720 self.window_mut().next_frame.content_mask_stack.pop();
721 result
722 } else {
723 f(self)
724 }
725 }
726
727 /// Updates the global element offset relative to the current offset. This is used to implement
728 /// scrolling.
729 pub fn with_element_offset<R>(
730 &mut self,
731 offset: Point<Pixels>,
732 f: impl FnOnce(&mut Self) -> R,
733 ) -> R {
734 if offset.is_zero() {
735 return f(self);
736 };
737
738 let abs_offset = self.element_offset() + offset;
739 self.with_absolute_element_offset(abs_offset, f)
740 }
741
742 /// Updates the global element offset based on the given offset. This is used to implement
743 /// drag handles and other manual painting of elements.
744 pub fn with_absolute_element_offset<R>(
745 &mut self,
746 offset: Point<Pixels>,
747 f: impl FnOnce(&mut Self) -> R,
748 ) -> R {
749 self.window_mut()
750 .next_frame
751 .element_offset_stack
752 .push(offset);
753 let result = f(self);
754 self.window_mut().next_frame.element_offset_stack.pop();
755 result
756 }
757
758 /// Remove an asset from GPUI's cache
759 pub fn remove_cached_asset<A: Asset + 'static>(
760 &mut self,
761 source: &A::Source,
762 ) -> Option<A::Output> {
763 self.asset_cache.remove::<A>(source)
764 }
765
766 /// Asynchronously load an asset, if the asset hasn't finished loading this will return None.
767 /// Your view will be re-drawn once the asset has finished loading.
768 ///
769 /// Note that the multiple calls to this method will only result in one `Asset::load` call.
770 /// The results of that call will be cached, and returned on subsequent uses of this API.
771 ///
772 /// Use [Self::remove_cached_asset] to reload your asset.
773 pub fn use_cached_asset<A: Asset + 'static>(
774 &mut self,
775 source: &A::Source,
776 ) -> Option<A::Output> {
777 self.asset_cache.get::<A>(source).or_else(|| {
778 if let Some(asset) = self.use_asset::<A>(source) {
779 self.asset_cache
780 .insert::<A>(source.to_owned(), asset.clone());
781 Some(asset)
782 } else {
783 None
784 }
785 })
786 }
787
788 /// Asynchronously load an asset, if the asset hasn't finished loading this will return None.
789 /// Your view will be re-drawn once the asset has finished loading.
790 ///
791 /// Note that the multiple calls to this method will only result in one `Asset::load` call at a
792 /// time.
793 ///
794 /// This asset will not be cached by default, see [Self::use_cached_asset]
795 pub fn use_asset<A: Asset + 'static>(&mut self, source: &A::Source) -> Option<A::Output> {
796 let asset_id = (TypeId::of::<A>(), hash(source));
797 let mut is_first = false;
798 let task = self
799 .loading_assets
800 .remove(&asset_id)
801 .map(|boxed_task| *boxed_task.downcast::<Shared<Task<A::Output>>>().unwrap())
802 .unwrap_or_else(|| {
803 is_first = true;
804 let future = A::load(source.clone(), self);
805 let task = self.background_executor().spawn(future).shared();
806 task
807 });
808
809 task.clone().now_or_never().or_else(|| {
810 if is_first {
811 let parent_id = self.parent_view_id();
812 self.spawn({
813 let task = task.clone();
814 |mut cx| async move {
815 task.await;
816
817 cx.on_next_frame(move |cx| {
818 if let Some(parent_id) = parent_id {
819 cx.notify(parent_id)
820 } else {
821 cx.refresh()
822 }
823 });
824 }
825 })
826 .detach();
827 }
828
829 self.loading_assets.insert(asset_id, Box::new(task));
830
831 None
832 })
833 }
834
835 /// Obtain the current element offset.
836 pub fn element_offset(&self) -> Point<Pixels> {
837 self.window()
838 .next_frame
839 .element_offset_stack
840 .last()
841 .copied()
842 .unwrap_or_default()
843 }
844
845 /// Obtain the current content mask.
846 pub fn content_mask(&self) -> ContentMask<Pixels> {
847 self.window()
848 .next_frame
849 .content_mask_stack
850 .last()
851 .cloned()
852 .unwrap_or_else(|| ContentMask {
853 bounds: Bounds {
854 origin: Point::default(),
855 size: self.window().viewport_size,
856 },
857 })
858 }
859
860 /// The size of an em for the base font of the application. Adjusting this value allows the
861 /// UI to scale, just like zooming a web page.
862 pub fn rem_size(&self) -> Pixels {
863 self.window().rem_size
864 }
865
866 /// Updates or initializes state for an element with the given id that lives across multiple
867 /// frames. If an element with this ID existed in the rendered frame, its state will be passed
868 /// to the given closure. The state returned by the closure will be stored so it can be referenced
869 /// when drawing the next frame.
870 pub fn with_element_state<S, R>(
871 &mut self,
872 element_id: Option<ElementId>,
873 f: impl FnOnce(Option<Option<S>>, &mut Self) -> (R, Option<S>),
874 ) -> R
875 where
876 S: 'static,
877 {
878 let id_is_none = element_id.is_none();
879 self.with_element_id(element_id, |cx| {
880 if id_is_none {
881 let (result, state) = f(None, cx);
882 debug_assert!(state.is_none(), "you must not return an element state when passing None for the element id");
883 result
884 } else {
885 let global_id = cx.window().element_id_stack.clone();
886 let key = (global_id, TypeId::of::<S>());
887 cx.window.next_frame.accessed_element_states.push(key.clone());
888
889 if let Some(any) = cx
890 .window_mut()
891 .next_frame
892 .element_states
893 .remove(&key)
894 .or_else(|| {
895 cx.window_mut()
896 .rendered_frame
897 .element_states
898 .remove(&key)
899 })
900 {
901 let ElementStateBox {
902 inner,
903 #[cfg(debug_assertions)]
904 type_name
905 } = any;
906 // Using the extra inner option to avoid needing to reallocate a new box.
907 let mut state_box = inner
908 .downcast::<Option<S>>()
909 .map_err(|_| {
910 #[cfg(debug_assertions)]
911 {
912 anyhow::anyhow!(
913 "invalid element state type for id, requested_type {:?}, actual type: {:?}",
914 std::any::type_name::<S>(),
915 type_name
916 )
917 }
918
919 #[cfg(not(debug_assertions))]
920 {
921 anyhow::anyhow!(
922 "invalid element state type for id, requested_type {:?}",
923 std::any::type_name::<S>(),
924 )
925 }
926 })
927 .unwrap();
928
929 // Actual: Option<AnyElement> <- View
930 // Requested: () <- AnyElement
931 let state = state_box
932 .take()
933 .expect("reentrant call to with_element_state for the same state type and element id");
934 let (result, state) = f(Some(Some(state)), cx);
935 state_box.replace(state.expect("you must return "));
936 cx.window_mut()
937 .next_frame
938 .element_states
939 .insert(key, ElementStateBox {
940 inner: state_box,
941 #[cfg(debug_assertions)]
942 type_name
943 });
944 result
945 } else {
946 let (result, state) = f(Some(None), cx);
947 cx.window_mut()
948 .next_frame
949 .element_states
950 .insert(key,
951 ElementStateBox {
952 inner: Box::new(Some(state.expect("you must return Some<State> when you pass some element id"))),
953 #[cfg(debug_assertions)]
954 type_name: std::any::type_name::<S>()
955 }
956
957 );
958 result
959 }
960 }
961 })
962 }
963
964 /// Defers the drawing of the given element, scheduling it to be painted on top of the currently-drawn tree
965 /// at a later time. The `priority` parameter determines the drawing order relative to other deferred elements,
966 /// with higher values being drawn on top.
967 pub fn defer_draw(
968 &mut self,
969 element: AnyElement,
970 absolute_offset: Point<Pixels>,
971 priority: usize,
972 ) {
973 let window = &mut self.cx.window;
974 assert_eq!(
975 window.draw_phase,
976 DrawPhase::Layout,
977 "defer_draw can only be called during before_layout or after_layout"
978 );
979 let parent_node = window.next_frame.dispatch_tree.active_node_id().unwrap();
980 window.next_frame.deferred_draws.push(DeferredDraw {
981 parent_node,
982 element_id_stack: window.element_id_stack.clone(),
983 text_style_stack: window.text_style_stack.clone(),
984 priority,
985 element: Some(element),
986 absolute_offset,
987 layout_range: AfterLayoutIndex::default()..AfterLayoutIndex::default(),
988 paint_range: PaintIndex::default()..PaintIndex::default(),
989 });
990 }
991
992 /// Creates a new painting layer for the specified bounds. A "layer" is a batch
993 /// of geometry that are non-overlapping and have the same draw order. This is typically used
994 /// for performance reasons.
995 pub fn paint_layer<R>(&mut self, bounds: Bounds<Pixels>, f: impl FnOnce(&mut Self) -> R) -> R {
996 let scale_factor = self.scale_factor();
997 let content_mask = self.content_mask();
998 let clipped_bounds = bounds.intersect(&content_mask.bounds);
999 if !clipped_bounds.is_empty() {
1000 self.window
1001 .next_frame
1002 .scene
1003 .push_layer(clipped_bounds.scale(scale_factor));
1004 }
1005
1006 let result = f(self);
1007
1008 if !clipped_bounds.is_empty() {
1009 self.window.next_frame.scene.pop_layer();
1010 }
1011
1012 result
1013 }
1014
1015 /// Paint one or more drop shadows into the scene for the next frame at the current z-index.
1016 pub fn paint_shadows(
1017 &mut self,
1018 bounds: Bounds<Pixels>,
1019 corner_radii: Corners<Pixels>,
1020 shadows: &[BoxShadow],
1021 ) {
1022 let scale_factor = self.scale_factor();
1023 let content_mask = self.content_mask();
1024 for shadow in shadows {
1025 let mut shadow_bounds = bounds;
1026 shadow_bounds.origin += shadow.offset;
1027 shadow_bounds.dilate(shadow.spread_radius);
1028 self.window.next_frame.scene.insert_primitive(Shadow {
1029 order: 0,
1030 blur_radius: shadow.blur_radius.scale(scale_factor),
1031 bounds: shadow_bounds.scale(scale_factor),
1032 content_mask: content_mask.scale(scale_factor),
1033 corner_radii: corner_radii.scale(scale_factor),
1034 color: shadow.color,
1035 });
1036 }
1037 }
1038
1039 /// Paint one or more quads into the scene for the next frame at the current stacking context.
1040 /// Quads are colored rectangular regions with an optional background, border, and corner radius.
1041 /// see [`fill`](crate::fill), [`outline`](crate::outline), and [`quad`](crate::quad) to construct this type.
1042 pub fn paint_quad(&mut self, quad: PaintQuad) {
1043 let scale_factor = self.scale_factor();
1044 let content_mask = self.content_mask();
1045 self.window.next_frame.scene.insert_primitive(Quad {
1046 order: 0,
1047 pad: 0,
1048 bounds: quad.bounds.scale(scale_factor),
1049 content_mask: content_mask.scale(scale_factor),
1050 background: quad.background,
1051 border_color: quad.border_color,
1052 corner_radii: quad.corner_radii.scale(scale_factor),
1053 border_widths: quad.border_widths.scale(scale_factor),
1054 });
1055 }
1056
1057 /// Paint the given `Path` into the scene for the next frame at the current z-index.
1058 pub fn paint_path(&mut self, mut path: Path<Pixels>, color: impl Into<Hsla>) {
1059 let scale_factor = self.scale_factor();
1060 let content_mask = self.content_mask();
1061 path.content_mask = content_mask;
1062 path.color = color.into();
1063 self.window
1064 .next_frame
1065 .scene
1066 .insert_primitive(path.scale(scale_factor));
1067 }
1068
1069 /// Paint an underline into the scene for the next frame at the current z-index.
1070 pub fn paint_underline(
1071 &mut self,
1072 origin: Point<Pixels>,
1073 width: Pixels,
1074 style: &UnderlineStyle,
1075 ) {
1076 let scale_factor = self.scale_factor();
1077 let height = if style.wavy {
1078 style.thickness * 3.
1079 } else {
1080 style.thickness
1081 };
1082 let bounds = Bounds {
1083 origin,
1084 size: size(width, height),
1085 };
1086 let content_mask = self.content_mask();
1087
1088 self.window.next_frame.scene.insert_primitive(Underline {
1089 order: 0,
1090 pad: 0,
1091 bounds: bounds.scale(scale_factor),
1092 content_mask: content_mask.scale(scale_factor),
1093 color: style.color.unwrap_or_default(),
1094 thickness: style.thickness.scale(scale_factor),
1095 wavy: style.wavy,
1096 });
1097 }
1098
1099 /// Paint a strikethrough into the scene for the next frame at the current z-index.
1100 pub fn paint_strikethrough(
1101 &mut self,
1102 origin: Point<Pixels>,
1103 width: Pixels,
1104 style: &StrikethroughStyle,
1105 ) {
1106 let scale_factor = self.scale_factor();
1107 let height = style.thickness;
1108 let bounds = Bounds {
1109 origin,
1110 size: size(width, height),
1111 };
1112 let content_mask = self.content_mask();
1113
1114 self.window.next_frame.scene.insert_primitive(Underline {
1115 order: 0,
1116 pad: 0,
1117 bounds: bounds.scale(scale_factor),
1118 content_mask: content_mask.scale(scale_factor),
1119 thickness: style.thickness.scale(scale_factor),
1120 color: style.color.unwrap_or_default(),
1121 wavy: false,
1122 });
1123 }
1124
1125 /// Paints a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index.
1126 ///
1127 /// The y component of the origin is the baseline of the glyph.
1128 /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or
1129 /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).
1130 /// This method is only useful if you need to paint a single glyph that has already been shaped.
1131 pub fn paint_glyph(
1132 &mut self,
1133 origin: Point<Pixels>,
1134 font_id: FontId,
1135 glyph_id: GlyphId,
1136 font_size: Pixels,
1137 color: Hsla,
1138 ) -> Result<()> {
1139 let scale_factor = self.scale_factor();
1140 let glyph_origin = origin.scale(scale_factor);
1141 let subpixel_variant = Point {
1142 x: (glyph_origin.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
1143 y: (glyph_origin.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
1144 };
1145 let params = RenderGlyphParams {
1146 font_id,
1147 glyph_id,
1148 font_size,
1149 subpixel_variant,
1150 scale_factor,
1151 is_emoji: false,
1152 };
1153
1154 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
1155 if !raster_bounds.is_zero() {
1156 let tile =
1157 self.window
1158 .sprite_atlas
1159 .get_or_insert_with(¶ms.clone().into(), &mut || {
1160 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
1161 Ok((size, Cow::Owned(bytes)))
1162 })?;
1163 let bounds = Bounds {
1164 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
1165 size: tile.bounds.size.map(Into::into),
1166 };
1167 let content_mask = self.content_mask().scale(scale_factor);
1168 self.window
1169 .next_frame
1170 .scene
1171 .insert_primitive(MonochromeSprite {
1172 order: 0,
1173 pad: 0,
1174 bounds,
1175 content_mask,
1176 color,
1177 tile,
1178 transformation: TransformationMatrix::unit(),
1179 });
1180 }
1181 Ok(())
1182 }
1183
1184 /// Paints an emoji glyph into the scene for the next frame at the current z-index.
1185 ///
1186 /// The y component of the origin is the baseline of the glyph.
1187 /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or
1188 /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).
1189 /// This method is only useful if you need to paint a single emoji that has already been shaped.
1190 pub fn paint_emoji(
1191 &mut self,
1192 origin: Point<Pixels>,
1193 font_id: FontId,
1194 glyph_id: GlyphId,
1195 font_size: Pixels,
1196 ) -> Result<()> {
1197 let scale_factor = self.scale_factor();
1198 let glyph_origin = origin.scale(scale_factor);
1199 let params = RenderGlyphParams {
1200 font_id,
1201 glyph_id,
1202 font_size,
1203 // We don't render emojis with subpixel variants.
1204 subpixel_variant: Default::default(),
1205 scale_factor,
1206 is_emoji: true,
1207 };
1208
1209 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
1210 if !raster_bounds.is_zero() {
1211 let tile =
1212 self.window
1213 .sprite_atlas
1214 .get_or_insert_with(¶ms.clone().into(), &mut || {
1215 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
1216 Ok((size, Cow::Owned(bytes)))
1217 })?;
1218 let bounds = Bounds {
1219 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
1220 size: tile.bounds.size.map(Into::into),
1221 };
1222 let content_mask = self.content_mask().scale(scale_factor);
1223
1224 self.window
1225 .next_frame
1226 .scene
1227 .insert_primitive(PolychromeSprite {
1228 order: 0,
1229 grayscale: false,
1230 bounds,
1231 corner_radii: Default::default(),
1232 content_mask,
1233 tile,
1234 });
1235 }
1236 Ok(())
1237 }
1238
1239 /// Paint a monochrome SVG into the scene for the next frame at the current stacking context.
1240 pub fn paint_svg(
1241 &mut self,
1242 bounds: Bounds<Pixels>,
1243 path: SharedString,
1244 transformation: TransformationMatrix,
1245 color: Hsla,
1246 ) -> Result<()> {
1247 let scale_factor = self.scale_factor();
1248 let bounds = bounds.scale(scale_factor);
1249 // Render the SVG at twice the size to get a higher quality result.
1250 let params = RenderSvgParams {
1251 path,
1252 size: bounds
1253 .size
1254 .map(|pixels| DevicePixels::from((pixels.0 * 2.).ceil() as i32)),
1255 };
1256
1257 let tile =
1258 self.window
1259 .sprite_atlas
1260 .get_or_insert_with(¶ms.clone().into(), &mut || {
1261 let bytes = self.svg_renderer.render(¶ms)?;
1262 Ok((params.size, Cow::Owned(bytes)))
1263 })?;
1264 let content_mask = self.content_mask().scale(scale_factor);
1265
1266 self.window
1267 .next_frame
1268 .scene
1269 .insert_primitive(MonochromeSprite {
1270 order: 0,
1271 pad: 0,
1272 bounds,
1273 content_mask,
1274 color,
1275 tile,
1276 transformation,
1277 });
1278
1279 Ok(())
1280 }
1281
1282 /// Paint an image into the scene for the next frame at the current z-index.
1283 pub fn paint_image(
1284 &mut self,
1285 bounds: Bounds<Pixels>,
1286 corner_radii: Corners<Pixels>,
1287 data: Arc<ImageData>,
1288 grayscale: bool,
1289 ) -> Result<()> {
1290 let scale_factor = self.scale_factor();
1291 let bounds = bounds.scale(scale_factor);
1292 let params = RenderImageParams { image_id: data.id };
1293
1294 let tile = self
1295 .window
1296 .sprite_atlas
1297 .get_or_insert_with(¶ms.clone().into(), &mut || {
1298 Ok((data.size(), Cow::Borrowed(data.as_bytes())))
1299 })?;
1300 let content_mask = self.content_mask().scale(scale_factor);
1301 let corner_radii = corner_radii.scale(scale_factor);
1302
1303 self.window
1304 .next_frame
1305 .scene
1306 .insert_primitive(PolychromeSprite {
1307 order: 0,
1308 grayscale,
1309 bounds,
1310 content_mask,
1311 corner_radii,
1312 tile,
1313 });
1314 Ok(())
1315 }
1316
1317 /// Paint a surface into the scene for the next frame at the current z-index.
1318 #[cfg(target_os = "macos")]
1319 pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVImageBuffer) {
1320 let scale_factor = self.scale_factor();
1321 let bounds = bounds.scale(scale_factor);
1322 let content_mask = self.content_mask().scale(scale_factor);
1323 self.window
1324 .next_frame
1325 .scene
1326 .insert_primitive(crate::Surface {
1327 order: 0,
1328 bounds,
1329 content_mask,
1330 image_buffer,
1331 });
1332 }
1333
1334 #[must_use]
1335 /// Add a node to the layout tree for the current frame. Takes the `Style` of the element for which
1336 /// layout is being requested, along with the layout ids of any children. This method is called during
1337 /// calls to the `Element::layout` trait method and enables any element to participate in layout.
1338 pub fn request_layout(
1339 &mut self,
1340 style: &Style,
1341 children: impl IntoIterator<Item = LayoutId>,
1342 ) -> LayoutId {
1343 self.app.layout_id_buffer.clear();
1344 self.app.layout_id_buffer.extend(children);
1345 let rem_size = self.rem_size();
1346
1347 self.cx
1348 .window
1349 .layout_engine
1350 .as_mut()
1351 .unwrap()
1352 .before_layout(style, rem_size, &self.cx.app.layout_id_buffer)
1353 }
1354
1355 /// Add a node to the layout tree for the current frame. Instead of taking a `Style` and children,
1356 /// this variant takes a function that is invoked during layout so you can use arbitrary logic to
1357 /// determine the element's size. One place this is used internally is when measuring text.
1358 ///
1359 /// The given closure is invoked at layout time with the known dimensions and available space and
1360 /// returns a `Size`.
1361 pub fn request_measured_layout<
1362 F: FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut WindowContext) -> Size<Pixels>
1363 + 'static,
1364 >(
1365 &mut self,
1366 style: Style,
1367 measure: F,
1368 ) -> LayoutId {
1369 let rem_size = self.rem_size();
1370 self.window
1371 .layout_engine
1372 .as_mut()
1373 .unwrap()
1374 .request_measured_layout(style, rem_size, measure)
1375 }
1376
1377 /// Compute the layout for the given id within the given available space.
1378 /// This method is called for its side effect, typically by the framework prior to painting.
1379 /// After calling it, you can request the bounds of the given layout node id or any descendant.
1380 pub fn compute_layout(&mut self, layout_id: LayoutId, available_space: Size<AvailableSpace>) {
1381 let mut layout_engine = self.window.layout_engine.take().unwrap();
1382 layout_engine.compute_layout(layout_id, available_space, self);
1383 self.window.layout_engine = Some(layout_engine);
1384 }
1385
1386 /// Obtain the bounds computed for the given LayoutId relative to the window. This method will usually be invoked by
1387 /// GPUI itself automatically in order to pass your element its `Bounds` automatically.
1388 pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {
1389 let mut bounds = self
1390 .window
1391 .layout_engine
1392 .as_mut()
1393 .unwrap()
1394 .layout_bounds(layout_id)
1395 .map(Into::into);
1396 bounds.origin += self.element_offset();
1397 bounds
1398 }
1399
1400 /// This method should be called during `after_layout`. You can use
1401 /// the returned [Hitbox] during `paint` or in an event handler
1402 /// to determine whether the inserted hitbox was the topmost.
1403 pub fn insert_hitbox(&mut self, bounds: Bounds<Pixels>, opaque: bool) -> Hitbox {
1404 let content_mask = self.content_mask();
1405 let window = &mut self.window;
1406 let id = window.next_hitbox_id;
1407 window.next_hitbox_id.0 += 1;
1408 let hitbox = Hitbox {
1409 id,
1410 bounds,
1411 content_mask,
1412 opaque,
1413 };
1414 window.next_frame.hitboxes.push(hitbox.clone());
1415 hitbox
1416 }
1417
1418 /// Sets the key context for the current element. This context will be used to translate
1419 /// keybindings into actions.
1420 pub fn set_key_context(&mut self, context: KeyContext) {
1421 self.window
1422 .next_frame
1423 .dispatch_tree
1424 .set_key_context(context);
1425 }
1426
1427 /// Sets the focus handle for the current element. This handle will be used to manage focus state
1428 /// and keyboard event dispatch for the element.
1429 pub fn set_focus_handle(&mut self, focus_handle: &FocusHandle) {
1430 self.window
1431 .next_frame
1432 .dispatch_tree
1433 .set_focus_id(focus_handle.id);
1434 }
1435
1436 /// Sets the view id for the current element, which will be used to manage view caching.
1437 pub fn set_view_id(&mut self, view_id: EntityId) {
1438 self.window.next_frame.dispatch_tree.set_view_id(view_id);
1439 }
1440
1441 /// Get the last view id for the current element
1442 pub fn parent_view_id(&mut self) -> Option<EntityId> {
1443 self.window.next_frame.dispatch_tree.parent_view_id()
1444 }
1445
1446 /// Sets an input handler, such as [`ElementInputHandler`][element_input_handler], which interfaces with the
1447 /// platform to receive textual input with proper integration with concerns such
1448 /// as IME interactions. This handler will be active for the upcoming frame until the following frame is
1449 /// rendered.
1450 ///
1451 /// [element_input_handler]: crate::ElementInputHandler
1452 pub fn handle_input(&mut self, focus_handle: &FocusHandle, input_handler: impl InputHandler) {
1453 if focus_handle.is_focused(self) {
1454 let cx = self.to_async();
1455 self.window
1456 .next_frame
1457 .input_handlers
1458 .push(Some(PlatformInputHandler::new(cx, Box::new(input_handler))));
1459 }
1460 }
1461
1462 /// Register a mouse event listener on the window for the next frame. The type of event
1463 /// is determined by the first parameter of the given listener. When the next frame is rendered
1464 /// the listener will be cleared.
1465 pub fn on_mouse_event<Event: MouseEvent>(
1466 &mut self,
1467 mut handler: impl FnMut(&Event, DispatchPhase, &mut ElementContext) + 'static,
1468 ) {
1469 self.window.next_frame.mouse_listeners.push(Some(Box::new(
1470 move |event: &dyn Any, phase: DispatchPhase, cx: &mut ElementContext<'_>| {
1471 if let Some(event) = event.downcast_ref() {
1472 handler(event, phase, cx)
1473 }
1474 },
1475 )));
1476 }
1477
1478 /// Register a key event listener on the window for the next frame. The type of event
1479 /// is determined by the first parameter of the given listener. When the next frame is rendered
1480 /// the listener will be cleared.
1481 ///
1482 /// This is a fairly low-level method, so prefer using event handlers on elements unless you have
1483 /// a specific need to register a global listener.
1484 pub fn on_key_event<Event: KeyEvent>(
1485 &mut self,
1486 listener: impl Fn(&Event, DispatchPhase, &mut ElementContext) + 'static,
1487 ) {
1488 self.window.next_frame.dispatch_tree.on_key_event(Rc::new(
1489 move |event: &dyn Any, phase, cx: &mut ElementContext<'_>| {
1490 if let Some(event) = event.downcast_ref::<Event>() {
1491 listener(event, phase, cx)
1492 }
1493 },
1494 ));
1495 }
1496
1497 /// Register a modifiers changed event listener on the window for the next frame.
1498 ///
1499 /// This is a fairly low-level method, so prefer using event handlers on elements unless you have
1500 /// a specific need to register a global listener.
1501 pub fn on_modifiers_changed(
1502 &mut self,
1503 listener: impl Fn(&ModifiersChangedEvent, &mut ElementContext) + 'static,
1504 ) {
1505 self.window
1506 .next_frame
1507 .dispatch_tree
1508 .on_modifiers_changed(Rc::new(
1509 move |event: &ModifiersChangedEvent, cx: &mut ElementContext<'_>| {
1510 listener(event, cx)
1511 },
1512 ));
1513 }
1514}