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