druid/
contexts.rs

1// Copyright 2020 The Druid Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! The context types that are passed into various widget methods.
16
17use std::{
18    any::{Any, TypeId},
19    collections::{HashMap, VecDeque},
20    ops::{Deref, DerefMut},
21    rc::Rc,
22    time::Duration,
23};
24use tracing::{error, trace, warn};
25
26use crate::commands::SCROLL_TO_VIEW;
27use crate::core::{CommandQueue, CursorChange, FocusChange, WidgetState};
28use crate::env::KeyLike;
29use crate::menu::ContextMenu;
30use crate::piet::{Piet, PietText, RenderContext};
31use crate::shell::text::Event as ImeInvalidation;
32use crate::shell::Region;
33use crate::text::{ImeHandlerRef, TextFieldRegistration};
34use crate::{
35    commands, sub_window::SubWindowDesc, widget::Widget, Affine, Command, Cursor, Data, Env,
36    ExtEventSink, Insets, Menu, Notification, Point, Rect, Scale, SingleUse, Size, Target,
37    TimerToken, Vec2, WidgetId, WindowConfig, WindowDesc, WindowHandle, WindowId,
38};
39
40/// A macro for implementing methods on multiple contexts.
41///
42/// There are a lot of methods defined on multiple contexts; this lets us only
43/// have to write them out once.
44macro_rules! impl_context_method {
45    ($ty:ty,  { $($method:item)+ } ) => {
46        impl $ty { $($method)+ }
47    };
48    ( $ty:ty, $($more:ty),+, { $($method:item)+ } ) => {
49        impl_context_method!($ty, { $($method)+ });
50        impl_context_method!($($more),+, { $($method)+ });
51    };
52}
53
54/// A macro for implementing context traits for multiple contexts.
55macro_rules! impl_context_trait {
56    ($tr:ty => $ty:ty,  { $($method:item)+ } ) => {
57        impl $tr for $ty { $($method)+ }
58    };
59    ($tr:ty => $ty:ty, $($more:ty),+, { $($method:item)+ } ) => {
60        impl_context_trait!($tr => $ty, { $($method)+ });
61        impl_context_trait!($tr => $($more),+, { $($method)+ });
62    };
63}
64
65/// Static state that is shared between most contexts.
66pub(crate) struct ContextState<'a> {
67    pub(crate) command_queue: &'a mut CommandQueue,
68    pub(crate) ext_handle: &'a ExtEventSink,
69    pub(crate) window_id: WindowId,
70    pub(crate) window: &'a WindowHandle,
71    pub(crate) text: PietText,
72    /// The id of the widget that currently has focus.
73    pub(crate) focus_widget: Option<WidgetId>,
74    pub(crate) root_app_data_type: TypeId,
75    pub(crate) timers: &'a mut HashMap<TimerToken, WidgetId>,
76    pub(crate) text_registrations: &'a mut Vec<TextFieldRegistration>,
77}
78
79/// A mutable context provided to event handling methods of widgets.
80///
81/// Widgets should call [`request_paint`] whenever an event causes a change
82/// in the widget's appearance, to schedule a repaint.
83///
84/// [`request_paint`]: #method.request_paint
85pub struct EventCtx<'a, 'b> {
86    pub(crate) state: &'a mut ContextState<'b>,
87    pub(crate) widget_state: &'a mut WidgetState,
88    pub(crate) notifications: &'a mut VecDeque<Notification>,
89    pub(crate) is_handled: bool,
90    pub(crate) is_root: bool,
91}
92
93/// A mutable context provided to the [`lifecycle`] method on widgets.
94///
95/// Certain methods on this context are only meaningful during the handling of
96/// specific lifecycle events; for instance [`register_child`]
97/// should only be called while handling [`LifeCycle::WidgetAdded`].
98///
99/// [`lifecycle`]: Widget::lifecycle
100/// [`register_child`]: #method.register_child
101/// [`LifeCycle::WidgetAdded`]: crate::LifeCycle::WidgetAdded
102pub struct LifeCycleCtx<'a, 'b> {
103    pub(crate) state: &'a mut ContextState<'b>,
104    pub(crate) widget_state: &'a mut WidgetState,
105}
106
107/// A mutable context provided to data update methods of widgets.
108///
109/// Widgets should call [`request_paint`] whenever a data change causes a change
110/// in the widget's appearance, to schedule a repaint.
111///
112/// [`request_paint`]: #method.request_paint
113pub struct UpdateCtx<'a, 'b> {
114    pub(crate) state: &'a mut ContextState<'b>,
115    pub(crate) widget_state: &'a mut WidgetState,
116    pub(crate) prev_env: Option<&'a Env>,
117    pub(crate) env: &'a Env,
118}
119
120/// A context provided to layout-handling methods of widgets.
121///
122/// As of now, the main service provided is access to a factory for
123/// creating text layout objects, which are likely to be useful
124/// during widget layout.
125pub struct LayoutCtx<'a, 'b> {
126    pub(crate) state: &'a mut ContextState<'b>,
127    pub(crate) widget_state: &'a mut WidgetState,
128}
129
130/// Z-order paint operations with transformations.
131pub(crate) struct ZOrderPaintOp {
132    pub z_index: u32,
133    pub paint_func: Box<dyn FnOnce(&mut PaintCtx) + 'static>,
134    pub transform: Affine,
135}
136
137/// A context passed to paint methods of widgets.
138///
139/// In addition to the API below, [`PaintCtx`] derefs to an implementation of
140/// the [`RenderContext`] trait, which defines the basic available drawing
141/// commands.
142pub struct PaintCtx<'a, 'b, 'c> {
143    pub(crate) state: &'a mut ContextState<'b>,
144    pub(crate) widget_state: &'a WidgetState,
145    /// The render context for actually painting.
146    pub render_ctx: &'a mut Piet<'c>,
147    /// The z-order paint operations.
148    pub(crate) z_ops: Vec<ZOrderPaintOp>,
149    /// The currently visible region.
150    pub(crate) region: Region,
151    /// The approximate depth in the tree at the time of painting.
152    pub(crate) depth: u32,
153}
154
155/// The state of a widget and its global context.
156pub struct State<'a> {
157    // currently the only method using the State struct is set_origin.
158    // the context state could be included into this struct to allow changes to context state
159    // changes from Context traits
160    // pub(crate) state: &'a mut ContextState<'b>,
161    pub(crate) widget_state: &'a mut WidgetState,
162}
163
164/// Convenience trait for code generic over contexts.
165///
166/// Methods that deal with commands and timers.
167/// Available to all contexts but [`PaintCtx`].
168pub trait ChangeCtx {
169    /// Submit a [`Command`] to be run after this event is handled. See [`submit_command`].
170    ///
171    /// [`submit_command`]: EventCtx::submit_command
172    fn submit_command(&mut self, cmd: impl Into<Command>);
173    /// Returns an [`ExtEventSink`] for submitting commands from other threads. See ['get_external_handle'].
174    ///
175    /// [`get_external_handle`]: EventCtx::get_external_handle
176    fn get_external_handle(&self) -> ExtEventSink;
177    /// Request a timer event. See [`request_timer`]
178    ///
179    /// [`request_timer`]: EventCtx::request_timer
180    fn request_timer(&mut self, deadline: Duration) -> TimerToken;
181
182    /// Returns the state of the widget.
183    ///
184    /// This method should only be used by the framework to do mergeups.
185    fn state(&mut self) -> State;
186}
187
188/// Convenience trait for invalidation and request methods available on multiple contexts.
189///
190/// These methods are available on [`EventCtx`], [`LifeCycleCtx`], and [`UpdateCtx`].
191pub trait RequestCtx: ChangeCtx {
192    /// Request a [`paint`] pass. See ['request_paint']
193    ///
194    /// ['request_paint']: EventCtx::request_paint
195    /// [`paint`]: Widget::paint
196    fn request_paint(&mut self);
197    /// Request a [`paint`] pass for redrawing a rectangle. See [`request_paint_rect`].
198    ///
199    /// [`request_paint_rect`]: EventCtx::request_paint_rect
200    /// [`paint`]: Widget::paint
201    fn request_paint_rect(&mut self, rect: Rect);
202    /// Request a layout pass. See [`request_layout`].
203    ///
204    /// [`request_layout`]: EventCtx::request_layout
205    fn request_layout(&mut self);
206    /// Request an animation frame. See [`request_anim_frame`].
207    ///
208    /// [`request_anim_frame`]: EventCtx::request_anim_frame
209    fn request_anim_frame(&mut self);
210    /// Indicate that your children have changed. See [`children_changed`].
211    ///
212    /// [`children_changed`]: EventCtx::children_changed
213    fn children_changed(&mut self);
214    /// Create a new sub-window. See [`new_sub_window`].
215    ///
216    /// [`new_sub_window`]: EventCtx::new_sub_window
217    fn new_sub_window<W: Widget<U> + 'static, U: Data>(
218        &mut self,
219        window_config: WindowConfig,
220        widget: W,
221        data: U,
222        env: Env,
223    ) -> WindowId;
224    /// Change the disabled state of this widget. See [`set_disabled`].
225    ///
226    /// [`set_disabled`]: EventCtx::set_disabled
227    fn set_disabled(&mut self, disabled: bool);
228    /// Indicate that text input state has changed. See [`invalidate_text_input`].
229    ///
230    /// [`invalidate_text_input`]: EventCtx::invalidate_text_input
231    fn invalidate_text_input(&mut self, event: ImeInvalidation);
232    /// Scrolls this widget into view.
233    ///
234    /// [`scroll_to_view`]: EventCtx::scroll_to_view
235    fn scroll_to_view(&mut self);
236    /// Scrolls the area into view. See [`scroll_area_to_view`].
237    ///
238    /// [`scroll_area_to_view`]: EventCtx::scroll_area_to_view
239    fn scroll_area_to_view(&mut self, area: Rect);
240}
241
242impl_context_trait!(
243    ChangeCtx => EventCtx<'_, '_>, UpdateCtx<'_, '_>, LifeCycleCtx<'_, '_>, LayoutCtx<'_, '_>,
244    {
245
246        fn submit_command(&mut self, cmd: impl Into<Command>) {
247            Self::submit_command(self, cmd)
248        }
249
250        fn get_external_handle(&self) -> ExtEventSink {
251            Self::get_external_handle(self)
252        }
253
254        fn request_timer(&mut self, deadline: Duration) -> TimerToken {
255            Self::request_timer(self, deadline)
256        }
257
258        fn state(&mut self) -> State {
259            State {
260                //state: &mut *self.state,
261                widget_state: &mut *self.widget_state,
262            }
263        }
264    }
265);
266
267impl_context_trait!(
268    RequestCtx => EventCtx<'_, '_>, UpdateCtx<'_, '_>, LifeCycleCtx<'_, '_>,
269    {
270        fn request_paint(&mut self) {
271            Self::request_paint(self)
272        }
273
274        fn request_paint_rect(&mut self, rect: Rect) {
275            Self::request_paint_rect(self, rect)
276        }
277
278        fn request_layout(&mut self) {
279            Self::request_layout(self)
280        }
281
282        fn request_anim_frame(&mut self) {
283            Self::request_anim_frame(self)
284        }
285
286        fn children_changed(&mut self) {
287            Self::children_changed(self)
288        }
289
290        fn new_sub_window<W: Widget<U> + 'static, U: Data>(
291            &mut self,
292            window_config: WindowConfig,
293            widget: W,
294            data: U,
295            env: Env,
296        ) -> WindowId {
297            Self::new_sub_window(self, window_config, widget, data, env)
298        }
299
300        fn set_disabled(&mut self, disabled: bool) {
301            Self::set_disabled(self, disabled)
302        }
303
304        fn invalidate_text_input(&mut self, event: ImeInvalidation) {
305            Self::invalidate_text_input(self, event)
306        }
307
308        fn scroll_to_view(&mut self) {
309            Self::scroll_to_view(self)
310        }
311
312        fn scroll_area_to_view(&mut self, area: Rect) {
313            Self::scroll_area_to_view(self, area)
314        }
315    }
316);
317
318// methods on everyone
319impl_context_method!(
320    EventCtx<'_, '_>,
321    UpdateCtx<'_, '_>,
322    LifeCycleCtx<'_, '_>,
323    PaintCtx<'_, '_, '_>,
324    LayoutCtx<'_, '_>,
325    {
326        /// get the `WidgetId` of the current widget.
327        pub fn widget_id(&self) -> WidgetId {
328            self.widget_state.id
329        }
330
331        /// Returns a reference to the current `WindowHandle`.
332        pub fn window(&self) -> &WindowHandle {
333            self.state.window
334        }
335
336        /// Get the `WindowId` of the current window.
337        pub fn window_id(&self) -> WindowId {
338            self.state.window_id
339        }
340
341        /// Get an object which can create text layouts.
342        pub fn text(&mut self) -> &mut PietText {
343            &mut self.state.text
344        }
345
346        /// The current window's [`Scale`].
347        ///
348        /// The returned [`Scale`] is a copy and thus its information will be stale after
349        /// the platform changes the window's scale. This means you can only rely on it
350        /// until the next [`Event::WindowScale`] event happens.
351        ///
352        /// [`Scale`]: crate::Scale
353        /// [`Event::WindowScale`]: crate::Event::WindowScale
354        pub fn scale(&self) -> Scale {
355            self.state.window.get_scale().unwrap_or_default()
356        }
357    }
358);
359
360// methods on everyone but layoutctx
361impl_context_method!(
362    EventCtx<'_, '_>,
363    UpdateCtx<'_, '_>,
364    LifeCycleCtx<'_, '_>,
365    PaintCtx<'_, '_, '_>,
366    {
367        /// The layout size.
368        ///
369        /// This is the layout size as ultimately determined by the parent
370        /// container, on the previous layout pass.
371        ///
372        /// Generally it will be the same as the size returned by the child widget's
373        /// [`layout`] method.
374        ///
375        /// [`layout`]: Widget::layout
376        pub fn size(&self) -> Size {
377            self.widget_state.size()
378        }
379
380        /// The origin of the widget in window coordinates, relative to the top left corner of the
381        /// content area.
382        pub fn window_origin(&self) -> Point {
383            self.widget_state.window_origin()
384        }
385
386        /// Convert a point from the widget's coordinate space to the window's.
387        ///
388        /// The returned point is relative to the content area; it excludes window chrome.
389        pub fn to_window(&self, widget_point: Point) -> Point {
390            self.window_origin() + widget_point.to_vec2()
391        }
392
393        /// Convert a point from the widget's coordinate space to the screen's.
394        /// See the [`Screen`] module
395        ///
396        /// [`Screen`]: crate::shell::Screen
397        pub fn to_screen(&self, widget_point: Point) -> Point {
398            let insets = self.window().content_insets();
399            let content_origin = self.window().get_position() + Vec2::new(insets.x0, insets.y0);
400            content_origin + self.to_window(widget_point).to_vec2()
401        }
402
403        /// Query the "hot" state of the widget.
404        ///
405        /// See [`WidgetPod::is_hot`] for additional information.
406        ///
407        /// [`WidgetPod::is_hot`]: crate::WidgetPod::is_hot
408        pub fn is_hot(&self) -> bool {
409            self.widget_state.is_hot
410        }
411
412        /// Query the "active" state of the widget.
413        ///
414        /// See [`WidgetPod::is_active`] for additional information.
415        ///
416        /// [`WidgetPod::is_active`]: crate::WidgetPod::is_active
417        pub fn is_active(&self) -> bool {
418            self.widget_state.is_active
419        }
420
421        /// The focus status of a widget.
422        ///
423        /// Returns `true` if this specific widget is focused.
424        /// To check if any descendants are focused use [`has_focus`].
425        ///
426        /// Focus means that the widget receives keyboard events.
427        ///
428        /// A widget can request focus using the [`request_focus`] method.
429        /// It's also possible to register for automatic focus via [`register_for_focus`].
430        ///
431        /// If a widget gains or loses focus it will get a [`LifeCycle::FocusChanged`] event.
432        ///
433        /// Only one widget at a time is focused. However due to the way events are routed,
434        /// all ancestors of that widget will also receive keyboard events.
435        ///
436        /// [`request_focus`]: EventCtx::request_focus
437        /// [`register_for_focus`]: LifeCycleCtx::register_for_focus
438        /// [`LifeCycle::FocusChanged`]: crate::LifeCycle::FocusChanged
439        /// [`has_focus`]: #method.has_focus
440        pub fn is_focused(&self) -> bool {
441            self.state.focus_widget == Some(self.widget_id())
442        }
443
444        /// The (tree) focus status of a widget.
445        ///
446        /// Returns `true` if either this specific widget or any one of its descendants is focused.
447        /// To check if only this specific widget is focused use [`is_focused`],
448        ///
449        /// [`is_focused`]: crate::EventCtx::is_focused
450        pub fn has_focus(&self) -> bool {
451            self.widget_state.has_focus
452        }
453
454        /// The disabled state of a widget.
455        ///
456        /// Returns `true` if this widget or any of its ancestors is explicitly disabled.
457        /// To make this widget explicitly disabled use [`set_disabled`].
458        ///
459        /// Disabled means that this widget should not change the state of the application. What
460        /// that means is not entirely clear but in any it should not change its data. Therefore
461        /// others can use this as a safety mechanism to prevent the application from entering an
462        /// illegal state.
463        /// For an example the decrease button of a counter of type `usize` should be disabled if the
464        /// value is `0`.
465        ///
466        /// [`set_disabled`]: crate::EventCtx::set_disabled
467        pub fn is_disabled(&self) -> bool {
468            self.widget_state.is_disabled()
469        }
470    }
471);
472
473impl_context_method!(EventCtx<'_, '_>, UpdateCtx<'_, '_>, {
474    /// Set the cursor icon.
475    ///
476    /// This setting will be retained until [`clear_cursor`] is called, but it will only take
477    /// effect when this widget is either [`hot`] or [`active`]. If a child widget also sets a
478    /// cursor, the child widget's cursor will take precedence. (If that isn't what you want, use
479    /// [`override_cursor`] instead.)
480    ///
481    /// [`clear_cursor`]: crate::EventCtx::clear_cursor
482    /// [`override_cursor`]: crate::EventCtx::override_cursor
483    /// [`hot`]: crate::EventCtx::is_hot
484    /// [`active`]: crate::EventCtx::is_active
485    pub fn set_cursor(&mut self, cursor: &Cursor) {
486        trace!("set_cursor {:?}", cursor);
487        self.widget_state.cursor_change = CursorChange::Set(cursor.clone());
488    }
489
490    /// Override the cursor icon.
491    ///
492    /// This setting will be retained until [`clear_cursor`] is called, but it will only take
493    /// effect when this widget is either [`hot`] or [`active`]. This will override the cursor
494    /// preferences of a child widget. (If that isn't what you want, use [`set_cursor`] instead.)
495    ///
496    /// [`clear_cursor`]: crate::EventCtx::clear_cursor
497    /// [`set_cursor`]: crate::EventCtx::set_cursor
498    /// [`hot`]: crate::EventCtx::is_hot
499    /// [`active`]: crate::EventCtx::is_active
500    pub fn override_cursor(&mut self, cursor: &Cursor) {
501        trace!("override_cursor {:?}", cursor);
502        self.widget_state.cursor_change = CursorChange::Override(cursor.clone());
503    }
504
505    /// Clear the cursor icon.
506    ///
507    /// This undoes the effect of [`set_cursor`] and [`override_cursor`].
508    ///
509    /// [`override_cursor`]: crate::EventCtx::override_cursor
510    /// [`set_cursor`]: crate::EventCtx::set_cursor
511    pub fn clear_cursor(&mut self) {
512        trace!("clear_cursor");
513        self.widget_state.cursor_change = CursorChange::Default;
514    }
515});
516
517// methods on event, update and layout.
518impl_context_method!(EventCtx<'_, '_>, UpdateCtx<'_, '_>, LayoutCtx<'_, '_>, {
519    /// Indicate that your [`ViewContext`] has changed.
520    ///
521    /// This event is sent after layout is done and before paint is called. Note that you can still
522    /// receive this event even if there was no prior call to layout.
523    ///
524    /// Widgets must call this method after changing the clip region of their children.
525    /// Changes to the other parts of [`ViewContext`] (cursor position and global origin) are tracked
526    /// internally.
527    ///
528    /// [`ViewContext`]: crate::ViewContext
529    pub fn view_context_changed(&mut self) {
530        self.widget_state.view_context_changed = true;
531    }
532});
533
534// methods on event, update, and lifecycle
535impl_context_method!(EventCtx<'_, '_>, UpdateCtx<'_, '_>, LifeCycleCtx<'_, '_>, {
536    /// Request a [`paint`] pass. This is equivalent to calling
537    /// [`request_paint_rect`] for the widget's [`paint_rect`].
538    ///
539    /// [`paint`]: Widget::paint
540    /// [`request_paint_rect`]: #method.request_paint_rect
541    /// [`paint_rect`]: crate::WidgetPod::paint_rect
542    pub fn request_paint(&mut self) {
543        trace!("request_paint");
544        self.widget_state.invalid.set_rect(
545            self.widget_state.paint_rect() - self.widget_state.layout_rect().origin().to_vec2(),
546        );
547    }
548
549    /// Request a [`paint`] pass for redrawing a rectangle, which is given
550    /// relative to our layout rectangle.
551    ///
552    /// [`paint`]: Widget::paint
553    pub fn request_paint_rect(&mut self, rect: Rect) {
554        trace!("request_paint_rect {}", rect);
555        self.widget_state.invalid.add_rect(rect);
556    }
557
558    /// Request a layout pass.
559    ///
560    /// A Widget's [`layout`] method is always called when the widget tree
561    /// changes, or the window is resized.
562    ///
563    /// If your widget would like to have layout called at any other time,
564    /// (such as if it would like to change the layout of children in
565    /// response to some event) it must call this method.
566    ///
567    /// [`layout`]: Widget::layout
568    pub fn request_layout(&mut self) {
569        trace!("request_layout");
570        self.widget_state.needs_layout = true;
571    }
572
573    /// Request an [`AnimFrame`] event.
574    ///
575    /// Receiving [`AnimFrame`] does not inherently mean a `paint` invocation will follow.
576    /// If you want something actually painted you need to explicitly call [`request_paint`]
577    /// or [`request_paint_rect`] when handling the [`AnimFrame`] event.
578    ///
579    /// Note that not requesting paint when handling the [`AnimFrame`] event and then
580    /// recursively requesting another [`AnimFrame`] can lead to rapid event fire,
581    /// which is probably not what you want and would most likely be wasted compute cycles.
582    ///
583    /// [`AnimFrame`]: crate::Event::AnimFrame
584    /// [`request_paint`]: #method.request_paint
585    /// [`request_paint_rect`]: #method.request_paint_rect
586    pub fn request_anim_frame(&mut self) {
587        trace!("request_anim_frame");
588        self.widget_state.request_anim = true;
589    }
590
591    /// Indicate that your children have changed.
592    ///
593    /// Widgets must call this method after adding a new child, removing a child or changing which
594    /// children are hidden (see [`should_propagate_to_hidden`]).
595    ///
596    /// [`should_propagate_to_hidden`]: crate::Event::should_propagate_to_hidden
597    pub fn children_changed(&mut self) {
598        trace!("children_changed");
599        self.widget_state.children_changed = true;
600        self.widget_state.update_focus_chain = true;
601        self.request_layout();
602    }
603
604    /// Set the disabled state for this widget.
605    ///
606    /// Setting this to `false` does not mean a widget is not still disabled; for instance it may
607    /// still be disabled by an ancestor. See [`is_disabled`] for more information.
608    ///
609    /// Calling this method during [`LifeCycle::DisabledChanged`] has no effect.
610    ///
611    /// [`LifeCycle::DisabledChanged`]: crate::LifeCycle::DisabledChanged
612    /// [`is_disabled`]: EventCtx::is_disabled
613    pub fn set_disabled(&mut self, disabled: bool) {
614        // widget_state.children_disabled_changed is not set because we want to be able to delete
615        // changes that happened during DisabledChanged.
616        self.widget_state.is_explicitly_disabled_new = disabled;
617    }
618
619    /// Indicate that text input state has changed.
620    ///
621    /// A widget that accepts text input should call this anytime input state
622    /// (such as the text or the selection) changes as a result of a non text-input
623    /// event.
624    pub fn invalidate_text_input(&mut self, event: ImeInvalidation) {
625        let payload = commands::ImeInvalidation {
626            widget: self.widget_id(),
627            event,
628        };
629        let cmd = commands::INVALIDATE_IME
630            .with(payload)
631            .to(Target::Window(self.window_id()));
632        self.submit_command(cmd);
633    }
634
635    /// Create a new sub-window.
636    ///
637    /// The sub-window will have its app data synchronised with caller's nearest ancestor [`WidgetPod`].
638    /// 'U' must be the type of the nearest surrounding [`WidgetPod`]. The 'data' argument should be
639    /// the current value of data  for that widget.
640    ///
641    /// [`WidgetPod`]: crate::WidgetPod
642    // TODO - dynamically check that the type of the pod we are registering this on is the same as the type of the
643    // requirement. Needs type ids recorded. This goes wrong if you don't have a pod between you and a lens.
644    pub fn new_sub_window<W: Widget<U> + 'static, U: Data>(
645        &mut self,
646        window_config: WindowConfig,
647        widget: W,
648        data: U,
649        env: Env,
650    ) -> WindowId {
651        trace!("new_sub_window");
652        let req = SubWindowDesc::new(self.widget_id(), window_config, widget, data, env);
653        let window_id = req.window_id;
654        self.widget_state
655            .add_sub_window_host(window_id, req.host_id);
656        self.submit_command(commands::NEW_SUB_WINDOW.with(SingleUse::new(req)));
657        window_id
658    }
659
660    /// Scrolls this widget into view.
661    ///
662    /// If this widget is only partially visible or not visible at all because of [`Scroll`]s
663    /// it is wrapped in, they will do the minimum amount of scrolling necessary to bring this
664    /// widget fully into view.
665    ///
666    /// If the widget is [`hidden`], this method has no effect.
667    ///
668    /// This functionality is achieved by sending a [`SCROLL_TO_VIEW`] notification.
669    ///
670    /// [`Scroll`]: crate::widget::Scroll
671    /// [`hidden`]: crate::Event::should_propagate_to_hidden
672    /// [`SCROLL_TO_VIEW`]: crate::commands::SCROLL_TO_VIEW
673    pub fn scroll_to_view(&mut self) {
674        self.scroll_area_to_view(self.size().to_rect())
675    }
676});
677
678// methods on everyone but paintctx
679impl_context_method!(
680    EventCtx<'_, '_>,
681    UpdateCtx<'_, '_>,
682    LifeCycleCtx<'_, '_>,
683    LayoutCtx<'_, '_>,
684    {
685        /// Submit a [`Command`] to be run after this event is handled.
686        ///
687        /// Commands are run in the order they are submitted; all commands
688        /// submitted during the handling of an event are executed before
689        /// the [`update`] method is called; events submitted during [`update`]
690        /// are handled after painting.
691        ///
692        /// [`Target::Auto`] commands will be sent to the window containing the widget.
693        ///
694        /// [`update`]: Widget::update
695        pub fn submit_command(&mut self, cmd: impl Into<Command>) {
696            trace!("submit_command");
697            self.state.submit_command(cmd.into())
698        }
699
700        /// Returns an [`ExtEventSink`] that can be moved between threads,
701        /// and can be used to submit commands back to the application.
702        pub fn get_external_handle(&self) -> ExtEventSink {
703            trace!("get_external_handle");
704            self.state.ext_handle.clone()
705        }
706
707        /// Request a timer event.
708        ///
709        /// The return value is a token, which can be used to associate the
710        /// request with the event.
711        pub fn request_timer(&mut self, deadline: Duration) -> TimerToken {
712            trace!("request_timer deadline={:?}", deadline);
713            self.state.request_timer(self.widget_state.id, deadline)
714        }
715    }
716);
717
718impl EventCtx<'_, '_> {
719    /// Submit a [`Notification`].
720    ///
721    /// The provided argument can be a [`Selector`] or a [`Command`]; this lets
722    /// us work with the existing API for adding a payload to a [`Selector`].
723    ///
724    /// If the argument is a `Command`, the command's target will be ignored.
725    ///
726    /// # Examples
727    ///
728    /// ```
729    /// # use druid::{Event, EventCtx, Selector};
730    /// const IMPORTANT_EVENT: Selector<String> = Selector::new("druid-example.important-event");
731    ///
732    /// fn check_event(ctx: &mut EventCtx, event: &Event) {
733    ///     if is_this_the_event_we_were_looking_for(event) {
734    ///         ctx.submit_notification(IMPORTANT_EVENT.with("That's the one".to_string()))
735    ///     }
736    /// }
737    ///
738    /// # fn is_this_the_event_we_were_looking_for(event: &Event) -> bool { true }
739    /// ```
740    ///
741    /// [`Selector`]: crate::Selector
742    pub fn submit_notification(&mut self, note: impl Into<Command>) {
743        trace!("submit_notification");
744        let note = note.into().into_notification(self.widget_state.id);
745        self.notifications.push_back(note);
746    }
747
748    /// Submit a [`Notification`] without warning.
749    ///
750    /// In contrast to [`submit_notification`], calling this method will not result in an
751    /// "unhandled notification" warning.
752    ///
753    /// [`submit_notification`]: crate::EventCtx::submit_notification
754    pub fn submit_notification_without_warning(&mut self, note: impl Into<Command>) {
755        trace!("submit_notification");
756        let note = note
757            .into()
758            .into_notification(self.widget_state.id)
759            .warn_if_unused(false);
760        self.notifications.push_back(note);
761    }
762
763    /// Set the "active" state of the widget.
764    ///
765    /// See [`EventCtx::is_active`](struct.EventCtx.html#method.is_active).
766    pub fn set_active(&mut self, active: bool) {
767        trace!("set_active({})", active);
768        self.widget_state.is_active = active;
769        // TODO: plumb mouse grab through to platform (through druid-shell)
770    }
771
772    /// Create a new window.
773    /// `T` must be the application's root `Data` type (the type provided to [`AppLauncher::launch`]).
774    ///
775    /// [`AppLauncher::launch`]: crate::AppLauncher::launch
776    pub fn new_window<T: Any>(&mut self, desc: WindowDesc<T>) {
777        trace!("new_window");
778        if self.state.root_app_data_type == TypeId::of::<T>() {
779            self.submit_command(
780                commands::NEW_WINDOW
781                    .with(SingleUse::new(Box::new(desc)))
782                    .to(Target::Global),
783            );
784        } else {
785            debug_panic!("EventCtx::new_window<T> - T must match the application data type.");
786        }
787    }
788
789    /// Show the context menu in the window containing the current widget.
790    /// `T` must be the application's root `Data` type (the type provided to [`AppLauncher::launch`]).
791    ///
792    /// [`AppLauncher::launch`]: crate::AppLauncher::launch
793    pub fn show_context_menu<T: Any>(&mut self, menu: Menu<T>, location: Point) {
794        trace!("show_context_menu");
795        if self.state.root_app_data_type == TypeId::of::<T>() {
796            let menu = ContextMenu { menu, location };
797            self.submit_command(
798                commands::SHOW_CONTEXT_MENU
799                    .with(SingleUse::new(Box::new(menu)))
800                    .to(Target::Window(self.state.window_id)),
801            );
802        } else {
803            debug_panic!(
804                "EventCtx::show_context_menu<T> - T must match the application data type."
805            );
806        }
807    }
808
809    /// Set the event as "handled", which stops its propagation to other
810    /// widgets.
811    pub fn set_handled(&mut self) {
812        trace!("set_handled");
813        self.is_handled = true;
814    }
815
816    /// Determine whether the event has been handled by some other widget.
817    pub fn is_handled(&self) -> bool {
818        self.is_handled
819    }
820
821    /// Request keyboard focus.
822    ///
823    /// Because only one widget can be focused at a time, multiple focus requests
824    /// from different widgets during a single event cycle means that the last
825    /// widget that requests focus will override the previous requests.
826    ///
827    /// See [`is_focused`] for more information about focus.
828    ///
829    /// [`is_focused`]: struct.EventCtx.html#method.is_focused
830    pub fn request_focus(&mut self) {
831        trace!("request_focus");
832        // We need to send the request even if we're currently focused,
833        // because we may have a sibling widget that already requested focus
834        // and we have no way of knowing that yet. We need to override that
835        // to deliver on the "last focus request wins" promise.
836        let id = self.widget_id();
837        self.widget_state.request_focus = Some(FocusChange::Focus(id));
838    }
839
840    /// Transfer focus to the widget with the given `WidgetId`.
841    ///
842    /// See [`is_focused`] for more information about focus.
843    ///
844    /// [`is_focused`]: struct.EventCtx.html#method.is_focused
845    pub fn set_focus(&mut self, target: WidgetId) {
846        trace!("set_focus target={:?}", target);
847        self.widget_state.request_focus = Some(FocusChange::Focus(target));
848    }
849
850    /// Transfer focus to the next focusable widget.
851    ///
852    /// This should only be called by a widget that currently has focus.
853    ///
854    /// See [`is_focused`] for more information about focus.
855    ///
856    /// [`is_focused`]: struct.EventCtx.html#method.is_focused
857    pub fn focus_next(&mut self) {
858        trace!("focus_next");
859        if self.has_focus() {
860            self.widget_state.request_focus = Some(FocusChange::Next);
861        } else {
862            warn!(
863                "focus_next can only be called by the currently \
864                            focused widget or one of its ancestors."
865            );
866        }
867    }
868
869    /// Transfer focus to the previous focusable widget.
870    ///
871    /// This should only be called by a widget that currently has focus.
872    ///
873    /// See [`is_focused`] for more information about focus.
874    ///
875    /// [`is_focused`]: struct.EventCtx.html#method.is_focused
876    pub fn focus_prev(&mut self) {
877        trace!("focus_prev");
878        if self.has_focus() {
879            self.widget_state.request_focus = Some(FocusChange::Previous);
880        } else {
881            warn!(
882                "focus_prev can only be called by the currently \
883                            focused widget or one of its ancestors."
884            );
885        }
886    }
887
888    /// Give up focus.
889    ///
890    /// This should only be called by a widget that currently has focus.
891    ///
892    /// See [`is_focused`] for more information about focus.
893    ///
894    /// [`is_focused`]: struct.EventCtx.html#method.is_focused
895    pub fn resign_focus(&mut self) {
896        trace!("resign_focus");
897        if self.has_focus() {
898            self.widget_state.request_focus = Some(FocusChange::Resign);
899        } else {
900            warn!(
901                "resign_focus can only be called by the currently focused widget \
902                 or one of its ancestors. ({:?})",
903                self.widget_id()
904            );
905        }
906    }
907
908    /// Request an update cycle.
909    ///
910    /// After this, `update` will be called on the widget in the next update cycle, even
911    /// if there's not a data change.
912    ///
913    /// The use case for this method is when a container widget synthesizes data for its
914    /// children. This is appropriate in specialized cases, but before reaching for this
915    /// method, consider whether it might be better to refactor to be more idiomatic, in
916    /// particular to make that data available in the app state.
917    pub fn request_update(&mut self) {
918        trace!("request_update");
919        self.widget_state.request_update = true;
920    }
921
922    /// Scrolls the area into view.
923    ///
924    /// If the area is only partially visible or not visible at all because of [`Scroll`]s
925    /// this widget is wrapped in, they will do the minimum amount of scrolling necessary to
926    /// bring the area fully into view.
927    ///
928    /// If the widget is [`hidden`], this method has no effect.
929    ///
930    /// [`Scroll`]: crate::widget::Scroll
931    /// [`hidden`]: crate::Event::should_propagate_to_hidden
932    pub fn scroll_area_to_view(&mut self, area: Rect) {
933        //TODO: only do something if this widget is not hidden
934        self.submit_notification_without_warning(
935            SCROLL_TO_VIEW.with(area + self.window_origin().to_vec2()),
936        );
937    }
938}
939
940impl UpdateCtx<'_, '_> {
941    /// Returns `true` if this widget or a descendent as explicitly requested
942    /// an update call.
943    ///
944    /// This should only be needed in advanced cases;
945    /// see [`EventCtx::request_update`] for more information.
946    ///
947    /// [`EventCtx::request_update`]: EventCtx::request_update
948    pub fn has_requested_update(&mut self) -> bool {
949        self.widget_state.request_update
950    }
951
952    /// Returns `true` if the current [`Env`] has changed since the previous
953    /// [`update`] call.
954    ///
955    /// [`update`]: Widget::update
956    pub fn env_changed(&self) -> bool {
957        self.prev_env.is_some()
958    }
959
960    /// Returns `true` if the given key has changed since the last [`update`]
961    /// call.
962    ///
963    /// The argument can be anything that is resolveable from the [`Env`],
964    /// such as a [`Key`] or a [`KeyOrValue`].
965    ///
966    /// [`update`]: Widget::update
967    /// [`Key`]: crate::Key
968    /// [`KeyOrValue`]: crate::KeyOrValue
969    pub fn env_key_changed<T>(&self, key: &impl KeyLike<T>) -> bool {
970        match self.prev_env.as_ref() {
971            Some(prev) => key.changed(prev, self.env),
972            None => false,
973        }
974    }
975
976    /// Scrolls the area into view.
977    ///
978    /// If the area is only partially visible or not visible at all because of [`Scroll`]s
979    /// this widget is wrapped in, they will do the minimum amount of scrolling necessary to
980    /// bring the area fully into view.
981    ///
982    /// If the widget is [`hidden`], this method has no effect.
983    ///
984    /// [`Scroll`]: crate::widget::Scroll
985    /// [`hidden`]: crate::Event::should_propagate_to_hidden
986    pub fn scroll_area_to_view(&mut self, area: Rect) {
987        //TODO: only do something if this widget is not hidden
988        self.submit_command(Command::new(
989            SCROLL_TO_VIEW,
990            area + self.window_origin().to_vec2(),
991            self.widget_id(),
992        ));
993    }
994}
995
996impl LifeCycleCtx<'_, '_> {
997    /// Registers a child widget.
998    ///
999    /// This should only be called in response to a `LifeCycle::WidgetAdded` event.
1000    ///
1001    /// In general, you should not need to call this method; it is handled by
1002    /// the `WidgetPod`.
1003    pub fn register_child(&mut self, child_id: WidgetId) {
1004        trace!("register_child id={:?}", child_id);
1005        self.widget_state.children.add(&child_id);
1006    }
1007
1008    /// Register this widget to be eligible to accept focus automatically.
1009    ///
1010    /// This should only be called in response to a [`LifeCycle::BuildFocusChain`] event.
1011    ///
1012    /// See [`EventCtx::is_focused`] for more information about focus.
1013    ///
1014    /// [`LifeCycle::BuildFocusChain`]: crate::LifeCycle::BuildFocusChain
1015    /// [`EventCtx::is_focused`]: EventCtx::is_focused
1016    pub fn register_for_focus(&mut self) {
1017        trace!("register_for_focus");
1018        self.widget_state.focus_chain.push(self.widget_id());
1019    }
1020
1021    /// Register this widget as accepting text input.
1022    pub fn register_text_input(&mut self, document: impl ImeHandlerRef + 'static) {
1023        let registration = TextFieldRegistration {
1024            document: Rc::new(document),
1025            widget_id: self.widget_id(),
1026        };
1027        self.state.text_registrations.push(registration);
1028    }
1029
1030    /// Scrolls the area into view.
1031    ///
1032    /// If the area is only partially visible or not visible at all because of [`Scroll`]s
1033    /// this widget is wrapped in, they will do the minimum amount of scrolling necessary to
1034    /// bring the area fully into view.
1035    ///
1036    /// If the widget is [`hidden`], this method has no effect.
1037    ///
1038    /// [`Scroll`]: crate::widget::Scroll
1039    /// [`hidden`]: crate::Event::should_propagate_to_hidden
1040    pub fn scroll_area_to_view(&mut self, area: Rect) {
1041        //TODO: only do something if this widget is not hidden
1042        self.submit_command(
1043            SCROLL_TO_VIEW
1044                .with(area + self.window_origin().to_vec2())
1045                .to(self.widget_id()),
1046        );
1047    }
1048}
1049
1050impl<'a, 'b> LayoutCtx<'a, 'b> {
1051    /// Set explicit paint [`Insets`] for this widget.
1052    ///
1053    /// You are not required to set explicit paint bounds unless you need
1054    /// to paint outside of your layout bounds. In this case, the argument
1055    /// should be an [`Insets`] struct that indicates where your widget
1056    /// needs to overpaint, relative to its bounds.
1057    ///
1058    /// For more information, see [`WidgetPod::paint_insets`].
1059    ///
1060    /// [`WidgetPod::paint_insets`]: crate::WidgetPod::paint_insets
1061    pub fn set_paint_insets(&mut self, insets: impl Into<Insets>) {
1062        let insets = insets.into();
1063        trace!("set_paint_insets {:?}", insets);
1064        self.widget_state.paint_insets = insets.nonnegative();
1065    }
1066
1067    /// Set an explicit baseline position for this widget.
1068    ///
1069    /// The baseline position is used to align widgets that contain text,
1070    /// such as buttons, labels, and other controls. It may also be used
1071    /// by other widgets that are opinionated about how they are aligned
1072    /// relative to neighbouring text, such as switches or checkboxes.
1073    ///
1074    /// The provided value should be the distance from the *bottom* of the
1075    /// widget to the baseline.
1076    pub fn set_baseline_offset(&mut self, baseline: f64) {
1077        trace!("set_baseline_offset {}", baseline);
1078        self.widget_state.baseline_offset = baseline
1079    }
1080}
1081
1082impl PaintCtx<'_, '_, '_> {
1083    /// The depth in the tree of the currently painting widget.
1084    ///
1085    /// This may be used in combination with [`paint_with_z_index`] in order
1086    /// to correctly order painting operations.
1087    ///
1088    /// The `depth` here may not be exact; it is only guaranteed that a child will
1089    /// have a greater depth than its parent.
1090    ///
1091    /// [`paint_with_z_index`]: #method.paint_with_z_index
1092    #[inline]
1093    pub fn depth(&self) -> u32 {
1094        self.depth
1095    }
1096
1097    /// Returns the region that needs to be repainted.
1098    #[inline]
1099    pub fn region(&self) -> &Region {
1100        &self.region
1101    }
1102
1103    /// Creates a temporary `PaintCtx` with a new visible region, and calls
1104    /// the provided function with that `PaintCtx`.
1105    ///
1106    /// This is used by containers to ensure that their children have the correct
1107    /// visible region given their layout.
1108    pub fn with_child_ctx(&mut self, region: impl Into<Region>, f: impl FnOnce(&mut PaintCtx)) {
1109        let mut child_ctx = PaintCtx {
1110            render_ctx: self.render_ctx,
1111            state: self.state,
1112            widget_state: self.widget_state,
1113            z_ops: Vec::new(),
1114            region: region.into(),
1115            depth: self.depth + 1,
1116        };
1117        f(&mut child_ctx);
1118        self.z_ops.append(&mut child_ctx.z_ops);
1119    }
1120
1121    /// Saves the current context, executes the closures, and restores the context.
1122    ///
1123    /// This is useful if you would like to transform or clip or otherwise
1124    /// modify the drawing context but do not want that modification to
1125    /// effect other widgets.
1126    ///
1127    /// # Examples
1128    ///
1129    /// ```
1130    /// # use druid::{Env, PaintCtx, RenderContext, theme};
1131    /// # struct T;
1132    /// # impl T {
1133    /// fn paint(&mut self, ctx: &mut PaintCtx, _data: &T, env: &Env) {
1134    ///     let clip_rect = ctx.size().to_rect().inset(5.0);
1135    ///     ctx.with_save(|ctx| {
1136    ///         ctx.clip(clip_rect);
1137    ///         ctx.stroke(clip_rect, &env.get(theme::PRIMARY_DARK), 5.0);
1138    ///     });
1139    /// }
1140    /// # }
1141    /// ```
1142    pub fn with_save(&mut self, f: impl FnOnce(&mut PaintCtx)) {
1143        if let Err(e) = self.render_ctx.save() {
1144            error!("Failed to save RenderContext: '{}'", e);
1145            return;
1146        }
1147
1148        f(self);
1149
1150        if let Err(e) = self.render_ctx.restore() {
1151            error!("Failed to restore RenderContext: '{}'", e);
1152        }
1153    }
1154
1155    /// Allows to specify order for paint operations.
1156    ///
1157    /// Larger `z_index` indicate that an operation will be executed later.
1158    pub fn paint_with_z_index(
1159        &mut self,
1160        z_index: u32,
1161        paint_func: impl FnOnce(&mut PaintCtx) + 'static,
1162    ) {
1163        let current_transform = self.render_ctx.current_transform();
1164        self.z_ops.push(ZOrderPaintOp {
1165            z_index,
1166            paint_func: Box::new(paint_func),
1167            transform: current_transform,
1168        })
1169    }
1170}
1171
1172impl<'a> ContextState<'a> {
1173    pub(crate) fn new<T: 'static>(
1174        command_queue: &'a mut CommandQueue,
1175        ext_handle: &'a ExtEventSink,
1176        window: &'a WindowHandle,
1177        window_id: WindowId,
1178        focus_widget: Option<WidgetId>,
1179        timers: &'a mut HashMap<TimerToken, WidgetId>,
1180        text_registrations: &'a mut Vec<TextFieldRegistration>,
1181    ) -> Self {
1182        ContextState {
1183            command_queue,
1184            ext_handle,
1185            window,
1186            window_id,
1187            focus_widget,
1188            timers,
1189            text_registrations,
1190            text: window.text(),
1191            root_app_data_type: TypeId::of::<T>(),
1192        }
1193    }
1194
1195    fn submit_command(&mut self, command: Command) {
1196        trace!("submit_command");
1197        self.command_queue
1198            .push_back(command.default_to(self.window_id.into()));
1199    }
1200
1201    fn request_timer(&mut self, widget_id: WidgetId, deadline: Duration) -> TimerToken {
1202        trace!("request_timer deadline={:?}", deadline);
1203        let timer_token = self.window.request_timer(deadline);
1204        self.timers.insert(timer_token, widget_id);
1205        timer_token
1206    }
1207}
1208
1209impl<'c> Deref for PaintCtx<'_, '_, 'c> {
1210    type Target = Piet<'c>;
1211
1212    fn deref(&self) -> &Self::Target {
1213        self.render_ctx
1214    }
1215}
1216
1217impl<'c> DerefMut for PaintCtx<'_, '_, 'c> {
1218    fn deref_mut(&mut self) -> &mut Self::Target {
1219        self.render_ctx
1220    }
1221}