1pub use ui_core::*;
28
29#[doc(hidden)]
34pub mod host_operation {}
35
36pub mod framework;
37mod runner;
38
39pub mod launch {
43 pub use crate::runner::{run, run_or_exit};
44 pub use ui_core::launch::*;
45}
46
47#[macro_export]
58macro_rules! main {
59 (definition = $definition:expr) => {
60 fn main() {
61 #[cfg(not(target_arch = "wasm32"))]
63 $crate::launch::run_or_exit(&$crate::framework::definition_launch_spec($definition()));
64 }
65 };
66 ($app:ty) => {
67 fn main() {
68 #[cfg(not(target_arch = "wasm32"))]
69 $crate::framework::run::<$app>();
70 }
71 };
72}
73
74#[macro_export]
86macro_rules! dev_reload_entry {
87 ($app:ty) => {
88 $crate::android_main!($crate::framework::run::<$app>);
89
90 #[cfg(feature = "thin")]
91 extern crate runtime_dylib;
92
93 #[cfg(feature = "thin")]
94 #[unsafe(no_mangle)]
95 pub unsafe extern "C" fn tilo_dev_apply(
96 id: *const u8,
97 id_len: usize,
98 state: *const u8,
99 state_len: usize,
100 out: *mut u8,
101 out_cap: usize,
102 ) -> isize {
103 let _ = (id, id_len);
104 unsafe {
105 $crate::framework::dev_reload::copy_window_state(state, state_len, out, out_cap)
106 }
107 }
108
109 #[cfg(feature = "thin")]
110 #[unsafe(no_mangle)]
111 pub extern "C" fn tilo_dev_linked_ui() -> *const () {
112 $crate::framework::dev_reload::linked_ui()
113 }
114
115 #[cfg(feature = "thin")]
116 #[unsafe(no_mangle)]
117 pub extern "C" fn tilo_dev_publish_root() -> i32 {
118 $crate::framework::dev_reload::publish_root::<$app>()
119 }
120
121 #[must_use]
126 pub fn definition() -> &'static $crate::prelude::ApplicationDefinition {
127 $crate::built_in_definition!($app)
128 }
129 };
130}
131
132#[macro_export]
139macro_rules! built_in_definition {
140 ($app:ty) => {{
141 $crate::register_built_in_surface(
142 <$app as $crate::framework::ResourceApp>::ID,
143 $crate::tilo_resource::committed_surface!(),
144 );
145 $crate::framework::definition::<$app>()
146 }};
147}
148
149#[doc(hidden)]
152pub fn register_built_in_surface(app_id: &str, bytes: Option<&'static [u8]>) {
153 if let Some(bytes) = bytes {
154 ui_core::app_surface::register_built_in(app_id, bytes);
155 }
156}
157
158pub use tilo_resource;
161
162pub use serde_json;
165pub use tilo_feedback as feedback;
167pub mod feedback_composer;
168pub use tilo_files as files;
172
173pub mod advanced {
177 pub use ui_core::taffy::{NodeId, TaffyTree};
178 pub use ui_core::vello::Scene;
179 pub use ui_core::vello::kurbo::Affine;
180 pub use ui_core::winit::event::WindowEvent;
181}
182
183pub mod prelude {
185 #[cfg(all(feature = "native", not(target_arch = "wasm32")))]
186 pub use crate::framework::run;
187 #[cfg(not(target_arch = "wasm32"))]
188 pub use crate::framework::testing::{HeadlessApp, TestApp};
189 pub use crate::framework::{
190 ActionControl, Actions, Bindable, Command, Dispatcher, Each, EditsText, EffectCx,
191 EffectStatus, Effected, Fixture, Form, Jobs, LaunchInput, Live, LiveRow, PersonRecord,
192 Records, ResourceApp, ResourceSelection, ResourceSurface, RunMode, SeedCx, Setting, Submit,
193 SurfaceCx, TextControl, ViewCx,
194 };
195 pub use tilo_resource::{
196 self, ActionCx, ActionDecl, ActionKind, Atom, Collection, Counter, Delta, Demand, Edit,
197 Effect, Id, Invoke, Json, Model, Outbox, Params, Path, PlainText, Refusal, Replica,
198 Resource, SearchEntry, Set, Settled, TextEdit, Undoing, resource,
199 };
200 pub use ui_core::i18n::LabelKey;
201
202 pub use ui_core::application::{
203 ANY_MEDIA_TYPE, AppComponent, ApplicationCatalog, ApplicationDefinition,
204 ComponentBehaviour, ComponentRunnerInputs, HostContext, HostContextInputs, LaunchTarget,
205 OpenFile, PlaybackHandoff, PreparedComponentInputs, RestoreInput,
206 };
207 pub use ui_core::application_view::{InstanceViewStore, SavedInstanceView};
208 pub use ui_core::launch::ComponentHostPreparer;
209 pub use ui_core::record::{RecordCheckout, RecordId, RecordKind, RecordSaveStatus};
210 pub use ui_core::storage::{Scope, SettingsSchema};
211 pub use ui_core::tilo_actions;
212 pub use ui_core::tilo_actions::{ActionError, ActionNeed, ActionRegistry, ExecutionLocus};
213 pub use ui_core::tokens::TextRole;
214 pub use ui_core::vello::kurbo::{Point, Rect, Size};
215 pub use ui_core::widget::data_table::{
216 ColumnDef, ColumnWidth, DataTable, TableModel, TableModelChange, TableRowState,
217 };
218 pub use ui_core::widget::resource_actions;
219 pub use ui_core::widget::resource_actions::{ActionForm, ActionValue};
220 pub use ui_core::widget::virtual_list::{
221 ListModel, ListModelChange, ListRowState, VirtualList,
222 };
223 pub use ui_core::widget::{
224 ActionEmitter, AudiencePresentationProvider, Banner, Button, Card, Checkbox, Collaborative,
225 Column, CompleteContentProvider, Container, Continuable, ControlBindingKind,
226 ControlBindingMetadata, Dropdown, Element, EmptyState, EventCtx, FilterCount, Filterable,
227 Filtered, FindBar, FindMatch, FindOptions, FindScope, Findable, FloatingSurfaceProvider,
228 FullscreenProvider, ModelView, NativeViewLifecycle, NavItem, NavList, NavMode, NavPane,
229 NavSection, NavShell, NumberInput, QrWidget, Row, Scrollable, SearchField,
230 SearchResultsView, Slider, Spacer, Spinner, Stack, Text, TextInput, Toggle, TreeNode,
231 TreeView, Widget, labeled_check, labeled_field,
232 };
233 pub use ui_core::{
234 LatestRequest, LatestTask, LocalState, PresenceCtx, RevisionHistory, SearchRegistry, State,
235 TextRenderer, Theme, UndoAccess, UndoRequest, UndoStatus, collaboration, column,
236 history_source, presence, row, search, stack,
237 };
238}
239
240#[cfg(test)]
241mod tests {
242 use super::prelude::*;
243 fn custom_event_handler(_event: &ui_core::winit::event::WindowEvent, ctx: &mut EventCtx<'_>) {
247 let _ = (&mut ctx.state, ctx.path, ctx.node_id);
250 }
251
252 struct CustomWidget {
255 inner: Text,
256 }
257
258 impl crate::widget::Decorator for CustomWidget {
259 type Inner = Text;
260
261 fn inner(&self) -> &Text {
262 &self.inner
263 }
264
265 fn inner_mut(&mut self) -> &mut Text {
266 &mut self.inner
267 }
268
269 fn native_input_snapshot(
270 &self,
271 _doc: &ui_core::widget::AppModel,
272 _path: &ui_core::widget::ModelPath,
273 ) -> Option<serde_json::Value> {
274 Some(serde_json::json!({ "width": self.inner.get_rect().width() }))
275 }
276
277 fn name(&self) -> &'static str {
278 "CustomWidget"
279 }
280 }
281
282 #[test]
283 fn prelude_exposes_the_integrated_custom_widget_surface() {
284 std::hint::black_box(custom_event_handler);
285 let custom = CustomWidget {
286 inner: Text::new("custom-widget"),
287 };
288 let widget: &dyn Widget = &custom;
289 assert_eq!(widget.name(), "CustomWidget");
290 assert_eq!(widget.get_rect(), custom.inner.get_rect());
291 std::hint::black_box(SearchRegistry::new());
292 std::hint::black_box(ActionForm::new("note", "Note", "save", "Save"));
293 }
294}