Seregon/StratoSDK

StratoSDK is a framework with a declarative approach similar to Flutter/React, written and designed entirely for Rust.

Rust/27.3 KB/No license
crates/strato-ui-core/src/core/view/mod.rs
1mod context;
2mod handle;
3 
4use crate::{
5 accessibility::{AccessibilityContent, ActionAccessibilityContent},
6 keymap, Action, AppContext, CursorInfo, Element, Entity,
7};
8 
9pub use self::{context::*, handle::*};
10 
11use super::EntityId;
12 
13pub enum FocusContext {
14 SelfFocused,
15 DescendentFocused(EntityId),
16}
17 
18impl FocusContext {
19 pub fn is_self_focused(&self) -> bool {
20 matches!(self, Self::SelfFocused)
21 }
22}
23 
24pub enum BlurContext {
25 SelfBlurred,
26 DescendentBlurred(EntityId),
27}
28 
29impl BlurContext {
30 pub fn is_self_blurred(&self) -> bool {
31 matches!(self, Self::SelfBlurred)
32 }
33}
34 
35/// An interface for interactive, renderable UI components.
36///
37/// Conceptually, an implementation of [`View`] is analogous to a React
38/// component - a structure that holds instance state and can be asked to render
39/// itself, a process that produces a tree of rendering primitives (in [`strato_ui`](crate),
40/// these are structures that implement [`Element`]; in React, these are DOM
41/// elements).
42///
43/// # Example
44///
45/// ```
46/// # use strato_ui_core::{*, elements::Rect};
47///
48/// struct MyView {}
49///
50/// impl Entity for MyView {
51/// type Event = ();
52/// }
53///
54/// impl View for MyView {
55/// fn ui_name() -> &'static str { "MyView" }
56/// fn render(&self, app: &AppContext) -> Box<dyn Element> {
57/// Rect::new().finish()
58/// }
59/// }
60/// ```
61pub trait View: Entity {
62 /// Returns a unique name for this implementation of View.
63 fn ui_name() -> &'static str;
64 
65 /// Produces an [`Element`] tree representation of this view.
66 fn render(&self, app: &AppContext) -> Box<dyn Element>;
67 
68 /// Handles the view or its descendent receiving focus.
69 /// Which view received focus is indicated by the [`FocusContext`].
70 fn on_focus(&mut self, _focus_ctx: &FocusContext, _ctx: &mut ViewContext<Self>) {}
71 
72 /// Accessibility (a11y) support for [`View`]s.
73 ///
74 /// Whenever the view is focused (i.e. [`View::on_focus`]), the provided a11y content
75 /// is read out through the native screen reader (e.g. VoiceOver in MacOS).
76 ///
77 /// While the contents default to [`None`] (i.e. no a11y content), each view
78 /// is encouraged to provide sensible a11y content so that visually-impaired users
79 /// can follow along in the application.
80 fn accessibility_contents(&self, _ctx: &AppContext) -> Option<AccessibilityContent> {
81 None
82 }
83 
84 /// Reports the active cursor position for the view, if any.
85 /// This only applies to [`View`]s that have some sort of text editor.
86 ///
87 /// We intentionally provide _immutable_ access to the [`ViewContext`];
88 /// querying the active cursor position shouldn't necessitate writes.
89 fn active_cursor_position(&self, _ctx: &ViewContext<Self>) -> Option<CursorInfo> {
90 None
91 }
92 
93 /// Handles the view or its descendent losing focus.
94 /// Which view lost focus is indicated by the [`BlurContext`].
95 fn on_blur(&mut self, _blur_ctx: &BlurContext, _ctx: &mut ViewContext<Self>) {}
96 
97 /// Handles the view's containing window closing.
98 fn on_window_closed(&mut self, _ctx: &mut ViewContext<Self>) {}
99 
100 /// Called when the view is transferred from one window to another.
101 /// Views can override this to update any window-specific state.
102 fn on_window_transferred(
103 &mut self,
104 _source_window_id: super::super::WindowId,
105 _target_window_id: super::super::WindowId,
106 _ctx: &mut ViewContext<Self>,
107 ) {
108 }
109 
110 /// Returns a representation of the current UI context for use in computing
111 /// the set of valid actions/keyboard shortcuts.
112 fn keymap_context(&self, _: &AppContext) -> keymap::Context {
113 Self::default_keymap_context()
114 }
115 
116 /// Returns the default context for a view.
117 fn default_keymap_context() -> keymap::Context {
118 let mut ctx = keymap::Context::default();
119 ctx.set.insert(Self::ui_name());
120 ctx
121 }
122 
123 /// Allows a view to hook into any interactions with it or its children.
124 ///
125 /// A valid interaction must be handled by the view or its children, and includes:
126 /// - all mouse events, except [`Event::MouseMoved`] and [`Event::ScrollWheel`]
127 /// - all keyboard events, including all [`CustomAction`]s and [`StandardAction::Paste`]
128 fn self_or_child_interacted_with(&self, _ctx: &mut ViewContext<Self>) {}
129 
130 /// Returns the current [`AccessibilityData`] for this view, if `Some`. Returning a valid
131 /// [`AccessibilityData`] struct here indicates that this view should belong in the
132 /// accessibility tree of this application.
133 fn accessibility_data(&self, _ctx: &mut ViewContext<Self>) -> Option<AccessibilityData> {
134 None
135 }
136}
137 
138/// The accessibility data of a current view.
139pub struct AccessibilityData {
140 /// The contents of the view.
141 pub content: String,
142}
143 
144/// An interface for a structure (typically a [`View`]) that handle actions
145/// of a particular type.
146pub trait TypedActionView {
147 type Action: Action;
148 
149 /// Handles an action of type [`Self::Action`](TypedActionView::Action)
150 /// that was dispatched from this view or any descendant.
151 fn handle_action(&mut self, _action: &Self::Action, _ctx: &mut ViewContext<Self>) {}
152 
153 /// TypedActionViews can implement another way to provide context about what’s going on with the app. After each `handle_action` call, the UI framework calls `action_accessibility_contents(&mut self, action: &Self::Action, ctx: &mut ViewContext<Self>) -> ActionAccessibilityContent`.
154 ///
155 /// ### When and how to use it?
156 /// This method should be implemented for all the meaningful Actions. For example, actions related to mouse movement are not meaningful, but action related to user copying the selected content - is.
157 /// If your Action enum has tons of actions, and only some of them are meaningful, you can use helper implementations from the `strato_ui::accessibility` (like `ActionAccessibilityContent::Default()` or `ActionAccessibility_content::from_debug()`).
158 fn action_accessibility_contents(
159 &mut self,
160 _action: &Self::Action,
161 _ctx: &mut ViewContext<Self>,
162 ) -> ActionAccessibilityContent {
163 ActionAccessibilityContent::default()
164 }
165}
166