Use one standard Iris resource bundle
This commit is contained in:
1 parent
d8bb1699a8
commit
213a0debb7
24 files changed
+177
-186
No files matched your search
@@ -52,11 +52,7 @@ impl DesktopAppState for Client {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(mut ui_state: DesktopUiState, rsc: &mut StdRsc<Self>, _: Proxy<Self::Event>) -> Self {
|
||||||
mut ui_state: DesktopUiState,
|
|
||||||
rsc: &mut DesktopRsc<Self>,
|
|
||||||
_: Proxy<Self::Event>,
|
|
||||||
) -> Self {
|
|
||||||
let screen = match ai_app::ui::fixture::open(rsc, &mut ui_state) {
|
let screen = match ai_app::ui::fixture::open(rsc, &mut ui_state) {
|
||||||
Ok(opened) => {
|
Ok(opened) => {
|
||||||
if let Some(message) = message_argv() {
|
if let Some(message) = message_argv() {
|
||||||
|
|||||||
@@ -158,11 +158,7 @@ fn fold_event(items: Vec<Item>, seq: u64) -> Vec<Item> {
|
|||||||
";
|
";
|
||||||
|
|
||||||
impl DesktopAppState for Client {
|
impl DesktopAppState for Client {
|
||||||
fn new(
|
fn new(mut ui_state: DesktopUiState, rsc: &mut StdRsc<Self>, _: Proxy<Self::Event>) -> Self {
|
||||||
mut ui_state: DesktopUiState,
|
|
||||||
rsc: &mut DesktopRsc<Self>,
|
|
||||||
_: Proxy<Self::Event>,
|
|
||||||
) -> Self {
|
|
||||||
let mut screen = ai_app::ui::build(rsc, &mut ui_state, synthetic_rows());
|
let mut screen = ai_app::ui::build(rsc, &mut ui_state, synthetic_rows());
|
||||||
screen.push_row(
|
screen.push_row(
|
||||||
rsc,
|
rsc,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use crate::client::transcript_fold::{TranscriptItem, fold_event};
|
|||||||
use crate::ui::{self, TranscriptScreen};
|
use crate::ui::{self, TranscriptScreen};
|
||||||
use android_view::jni::{JavaVM, objects::GlobalRef};
|
use android_view::jni::{JavaVM, objects::GlobalRef};
|
||||||
use event_model::SeqEvent;
|
use event_model::SeqEvent;
|
||||||
use iris::android::{AndroidAppState, AndroidRsc, AndroidUiState, HasAndroidUiState};
|
use iris::android::{AndroidAppState, AndroidUiState};
|
||||||
use iris::prelude::*;
|
use iris::prelude::*;
|
||||||
use std::{
|
use std::{
|
||||||
fs, mem,
|
fs, mem,
|
||||||
@@ -42,6 +42,7 @@ const POLL_MS: u64 = 16;
|
|||||||
|
|
||||||
const REPORT_MAX_HEIGHT_DP: f32 = 260.0;
|
const REPORT_MAX_HEIGHT_DP: f32 = 260.0;
|
||||||
|
|
||||||
|
#[derive(AndroidUiState)]
|
||||||
pub struct BenchClient {
|
pub struct BenchClient {
|
||||||
ui_state: AndroidUiState,
|
ui_state: AndroidUiState,
|
||||||
content: WeakWidget<WidgetPtr>,
|
content: WeakWidget<WidgetPtr>,
|
||||||
@@ -65,15 +66,6 @@ struct ImeState {
|
|||||||
hidden_events: u32,
|
hidden_events: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasAndroidUiState for BenchClient {
|
|
||||||
fn android_state(&self) -> &AndroidUiState {
|
|
||||||
&self.ui_state
|
|
||||||
}
|
|
||||||
fn android_state_mut(&mut self) -> &mut AndroidUiState {
|
|
||||||
&mut self.ui_state
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn placeholder<Rsc: HasEvents>(rsc: &mut Rsc, message: &str) -> StrongWidget {
|
fn placeholder<Rsc: HasEvents>(rsc: &mut Rsc, message: &str) -> StrongWidget {
|
||||||
wtext(message.to_string())
|
wtext(message.to_string())
|
||||||
.color(PaintId::WHITE)
|
.color(PaintId::WHITE)
|
||||||
@@ -121,7 +113,7 @@ fn battery_line(samples: &[i32]) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AndroidAppState for BenchClient {
|
impl AndroidAppState for BenchClient {
|
||||||
fn new(mut ui_state: AndroidUiState, rsc: &mut AndroidRsc<Self>) -> Self {
|
fn new(mut ui_state: AndroidUiState, rsc: &mut StdRsc<Self>) -> Self {
|
||||||
let content = WidgetPtr::new().add(rsc);
|
let content = WidgetPtr::new().add(rsc);
|
||||||
let loading = placeholder(rsc, "Loading fixture...");
|
let loading = placeholder(rsc, "Loading fixture...");
|
||||||
content(rsc).set(loading);
|
content(rsc).set(loading);
|
||||||
@@ -195,19 +187,15 @@ impl AndroidAppState for BenchClient {
|
|||||||
client
|
client
|
||||||
}
|
}
|
||||||
|
|
||||||
fn platform_ready(&mut self, _rsc: &mut AndroidRsc<Self>, vm: JavaVM, view: GlobalRef) {
|
fn platform_ready(&mut self, _rsc: &mut StdRsc<Self>, vm: JavaVM, view: GlobalRef) {
|
||||||
self.platform = Some(Arc::new(PlatformHandle::new(vm, view)));
|
self.platform = Some(Arc::new(PlatformHandle::new(vm, view)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn back_pressed(&mut self, _rsc: &mut AndroidRsc<Self>) -> bool {
|
fn back_pressed(&mut self, _rsc: &mut StdRsc<Self>) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_insets_changed(
|
fn on_insets_changed(&mut self, rsc: &mut StdRsc<Self>, insets: iris::android::WindowInsets) {
|
||||||
&mut self,
|
|
||||||
rsc: &mut AndroidRsc<Self>,
|
|
||||||
insets: iris::android::WindowInsets,
|
|
||||||
) {
|
|
||||||
if insets.top != self.last_top_pad {
|
if insets.top != self.last_top_pad {
|
||||||
self.last_top_pad = insets.top;
|
self.last_top_pad = insets.top;
|
||||||
let controls = bench_controls(rsc, insets.top);
|
let controls = bench_controls(rsc, insets.top);
|
||||||
@@ -255,7 +243,7 @@ impl AndroidAppState for BenchClient {
|
|||||||
|
|
||||||
const KEYBOARD_DIAGNOSTICS_DELAY_MS: u64 = 500;
|
const KEYBOARD_DIAGNOSTICS_DELAY_MS: u64 = 500;
|
||||||
|
|
||||||
type Rsc = AndroidRsc<BenchClient>;
|
type Rsc = StdRsc<BenchClient>;
|
||||||
|
|
||||||
/// What a report says about the `iris::input`/`iris::frame` trace, from
|
/// What a report says about the `iris::input`/`iris::frame` trace, from
|
||||||
/// the flag read at the start of what is being reported and again at the
|
/// the flag read at the start of what is being reported and again at the
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
use android_view::jni::JNIEnv;
|
use android_view::jni::JNIEnv;
|
||||||
use android_view::jni::objects::{JClass, JObject, JString};
|
use android_view::jni::objects::{JClass, JObject, JString};
|
||||||
use android_view::jni::sys::{jlong, jobjectArray};
|
use android_view::jni::sys::{jlong, jobjectArray};
|
||||||
use std::{path::Path, ptr, sync::OnceLock};
|
#[cfg(feature = "transcript-screen")]
|
||||||
|
use std::path::Path;
|
||||||
|
use std::{ptr, sync::OnceLock};
|
||||||
|
|
||||||
/// Gated with its one reader: the tabs demo links no `client-core` and so
|
/// Gated with its one reader: the tabs demo links no `client-core` and so
|
||||||
/// has no ring to lay out, and an ungated constant is a warning in that
|
/// has no ring to lay out, and an ungated constant is a warning in that
|
||||||
|
|||||||
+11
-17
@@ -8,12 +8,15 @@ use android_view::{
|
|||||||
register_view_class,
|
register_view_class,
|
||||||
};
|
};
|
||||||
#[cfg(not(feature = "transcript-screen"))]
|
#[cfg(not(feature = "transcript-screen"))]
|
||||||
use iris::android::{AndroidAppState, AndroidRsc, AndroidUiState, HasAndroidUiState};
|
use iris::{
|
||||||
use log::LevelFilter;
|
android::{AndroidAppState, AndroidUiState},
|
||||||
use std::{
|
macros::AndroidUiState,
|
||||||
ffi::c_void,
|
rsc::StdRsc,
|
||||||
path::{Path, PathBuf},
|
|
||||||
};
|
};
|
||||||
|
use log::LevelFilter;
|
||||||
|
use std::ffi::c_void;
|
||||||
|
#[cfg(feature = "transcript-screen")]
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
/// The app's own log ring and its upload -- only where `client-core` is
|
/// The app's own log ring and its upload -- only where `client-core` is
|
||||||
/// linked, which is every build that has a server to send to. The plain
|
/// linked, which is every build that has a server to send to. The plain
|
||||||
@@ -35,23 +38,14 @@ mod transcript_client;
|
|||||||
const VIEW_CLASS: &str = "dev/iris/android/demo/IrisView";
|
const VIEW_CLASS: &str = "dev/iris/android/demo/IrisView";
|
||||||
|
|
||||||
#[cfg(not(feature = "transcript-screen"))]
|
#[cfg(not(feature = "transcript-screen"))]
|
||||||
|
#[derive(AndroidUiState)]
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
ui_state: AndroidUiState,
|
ui_state: AndroidUiState,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "transcript-screen"))]
|
|
||||||
impl HasAndroidUiState for Client {
|
|
||||||
fn android_state(&self) -> &AndroidUiState {
|
|
||||||
&self.ui_state
|
|
||||||
}
|
|
||||||
fn android_state_mut(&mut self) -> &mut AndroidUiState {
|
|
||||||
&mut self.ui_state
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "transcript-screen"))]
|
#[cfg(not(feature = "transcript-screen"))]
|
||||||
impl AndroidAppState for Client {
|
impl AndroidAppState for Client {
|
||||||
fn new(mut ui_state: AndroidUiState, rsc: &mut AndroidRsc<Self>) -> Self {
|
fn new(mut ui_state: AndroidUiState, rsc: &mut StdRsc<Self>) -> Self {
|
||||||
// `widgets.info` is the winit example's frame-debug readout, kept
|
// `widgets.info` is the winit example's frame-debug readout, kept
|
||||||
// current from `DesktopAppState::window_event` -- android-view has
|
// current from `DesktopAppState::window_event` -- android-view has
|
||||||
// no per-frame hook to drive the equivalent from here yet, so it
|
// no per-frame hook to drive the equivalent from here yet, so it
|
||||||
@@ -60,7 +54,7 @@ impl AndroidAppState for Client {
|
|||||||
Self { ui_state }
|
Self { ui_state }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn back_pressed(&mut self, _rsc: &mut AndroidRsc<Self>) -> bool {
|
fn back_pressed(&mut self, _rsc: &mut StdRsc<Self>) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use crate::client::transcript_fold::{
|
|||||||
};
|
};
|
||||||
use crate::ui::{self, TranscriptScreen};
|
use crate::ui::{self, TranscriptScreen};
|
||||||
use event_model::SeqEvent;
|
use event_model::SeqEvent;
|
||||||
use iris::android::{AndroidAppState, AndroidRsc, AndroidUiState, HasAndroidUiState};
|
use iris::android::{AndroidAppState, AndroidUiState};
|
||||||
use iris::prelude::*;
|
use iris::prelude::*;
|
||||||
use std::{
|
use std::{
|
||||||
sync::{
|
sync::{
|
||||||
@@ -15,6 +15,7 @@ use std::{
|
|||||||
thread,
|
thread,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(AndroidUiState)]
|
||||||
pub struct TranscriptClient {
|
pub struct TranscriptClient {
|
||||||
ui_state: AndroidUiState,
|
ui_state: AndroidUiState,
|
||||||
/// The screen's own content -- everything under the fixed
|
/// The screen's own content -- everything under the fixed
|
||||||
@@ -29,15 +30,6 @@ pub struct TranscriptClient {
|
|||||||
generation: Arc<AtomicU64>,
|
generation: Arc<AtomicU64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasAndroidUiState for TranscriptClient {
|
|
||||||
fn android_state(&self) -> &AndroidUiState {
|
|
||||||
&self.ui_state
|
|
||||||
}
|
|
||||||
fn android_state_mut(&mut self) -> &mut AndroidUiState {
|
|
||||||
&mut self.ui_state
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_transport() -> Result<UreqTransport, String> {
|
fn build_transport() -> Result<UreqTransport, String> {
|
||||||
crate::android::enrollment::transport()
|
crate::android::enrollment::transport()
|
||||||
}
|
}
|
||||||
@@ -51,8 +43,8 @@ fn placeholder<Rsc: HasEvents>(rsc: &mut Rsc, message: &str) -> StrongWidget {
|
|||||||
.any()
|
.any()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frame_report_controls(rsc: &mut AndroidRsc<TranscriptClient>) -> WeakWidget {
|
fn frame_report_controls(rsc: &mut StdRsc<TranscriptClient>) -> WeakWidget {
|
||||||
type Rsc = AndroidRsc<TranscriptClient>;
|
type Rsc = StdRsc<TranscriptClient>;
|
||||||
let report_rect = rect(Srgba8::rgb(50, 50, 60))
|
let report_rect = rect(Srgba8::rgb(50, 50, 60))
|
||||||
.on(
|
.on(
|
||||||
CursorSense::click(),
|
CursorSense::click(),
|
||||||
@@ -98,7 +90,7 @@ fn frame_report_controls(rsc: &mut AndroidRsc<TranscriptClient>) -> WeakWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AndroidAppState for TranscriptClient {
|
impl AndroidAppState for TranscriptClient {
|
||||||
fn new(mut ui_state: AndroidUiState, rsc: &mut AndroidRsc<Self>) -> Self {
|
fn new(mut ui_state: AndroidUiState, rsc: &mut StdRsc<Self>) -> Self {
|
||||||
let content = WidgetPtr::new().add(rsc);
|
let content = WidgetPtr::new().add(rsc);
|
||||||
let loading = placeholder(rsc, "Loading sessions...");
|
let loading = placeholder(rsc, "Loading sessions...");
|
||||||
content(rsc).set(loading);
|
content(rsc).set(loading);
|
||||||
@@ -121,7 +113,7 @@ impl AndroidAppState for TranscriptClient {
|
|||||||
client
|
client
|
||||||
}
|
}
|
||||||
|
|
||||||
fn back_pressed(&mut self, _rsc: &mut AndroidRsc<Self>) -> bool {
|
fn back_pressed(&mut self, _rsc: &mut StdRsc<Self>) -> bool {
|
||||||
// No screen stack of its own -- same "let the activity finish"
|
// No screen stack of its own -- same "let the activity finish"
|
||||||
// answer `iris-android-app`'s tabs `Client` already gives.
|
// answer `iris-android-app`'s tabs `Client` already gives.
|
||||||
false
|
false
|
||||||
@@ -129,13 +121,13 @@ impl AndroidAppState for TranscriptClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TranscriptClient {
|
impl TranscriptClient {
|
||||||
fn show_message(&mut self, rsc: &mut AndroidRsc<Self>, message: &str) {
|
fn show_message(&mut self, rsc: &mut StdRsc<Self>, message: &str) {
|
||||||
let widget = placeholder(rsc, message);
|
let widget = placeholder(rsc, message);
|
||||||
(self.content)(rsc).set(widget);
|
(self.content)(rsc).set(widget);
|
||||||
self.screen = None;
|
self.screen = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_fetch_sessions(&mut self, rsc: &mut AndroidRsc<Self>) {
|
fn spawn_fetch_sessions(&mut self, rsc: &mut StdRsc<Self>) {
|
||||||
let redraw = rsc.tasks.redraw_handle();
|
let redraw = rsc.tasks.redraw_handle();
|
||||||
let my_generation = self.generation.load(Ordering::SeqCst);
|
let my_generation = self.generation.load(Ordering::SeqCst);
|
||||||
let generation = self.generation.clone();
|
let generation = self.generation.clone();
|
||||||
@@ -164,7 +156,7 @@ impl TranscriptClient {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_session(&mut self, rsc: &mut AndroidRsc<Self>, session_id: String) {
|
fn select_session(&mut self, rsc: &mut StdRsc<Self>, session_id: String) {
|
||||||
let my_generation = self.generation.fetch_add(1, Ordering::SeqCst) + 1;
|
let my_generation = self.generation.fetch_add(1, Ordering::SeqCst) + 1;
|
||||||
self.items.clear();
|
self.items.clear();
|
||||||
self.session_id = Some(session_id.clone());
|
self.session_id = Some(session_id.clone());
|
||||||
@@ -251,7 +243,7 @@ impl TranscriptClient {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rebuild_transcript(&mut self, rsc: &mut AndroidRsc<Self>) {
|
fn rebuild_transcript(&mut self, rsc: &mut StdRsc<Self>) {
|
||||||
let in_progress = self
|
let in_progress = self
|
||||||
.screen
|
.screen
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -279,7 +271,7 @@ impl TranscriptClient {
|
|||||||
self.screen = Some(screen);
|
self.screen = Some(screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_event(&mut self, rsc: &mut AndroidRsc<Self>, event: &SeqEvent) {
|
fn apply_event(&mut self, rsc: &mut StdRsc<Self>, event: &SeqEvent) {
|
||||||
let old_items = self.items.clone();
|
let old_items = self.items.clone();
|
||||||
self.items = fold_event(&self.items, event);
|
self.items = fold_event(&self.items, event);
|
||||||
match self.screen.as_mut() {
|
match self.screen.as_mut() {
|
||||||
|
|||||||
+9
-17
@@ -58,11 +58,7 @@ struct Client {
|
|||||||
impl DesktopAppState for Client {
|
impl DesktopAppState for Client {
|
||||||
type Event = AppEvent;
|
type Event = AppEvent;
|
||||||
|
|
||||||
fn new(
|
fn new(mut ui_state: DesktopUiState, rsc: &mut StdRsc<Self>, proxy: Proxy<AppEvent>) -> Self {
|
||||||
mut ui_state: DesktopUiState,
|
|
||||||
rsc: &mut DesktopRsc<Self>,
|
|
||||||
proxy: Proxy<AppEvent>,
|
|
||||||
) -> Self {
|
|
||||||
let (server, ca_pem) = super::startup::load_startup_config().unwrap_or_else(|e| {
|
let (server, ca_pem) = super::startup::load_startup_config().unwrap_or_else(|e| {
|
||||||
eprintln!("desktop-app: {e}");
|
eprintln!("desktop-app: {e}");
|
||||||
process::exit(2);
|
process::exit(2);
|
||||||
@@ -107,7 +103,7 @@ impl DesktopAppState for Client {
|
|||||||
client
|
client
|
||||||
}
|
}
|
||||||
|
|
||||||
fn event(&mut self, event: AppEvent, rsc: &mut DesktopRsc<Self>) {
|
fn event(&mut self, event: AppEvent, rsc: &mut StdRsc<Self>) {
|
||||||
match event {
|
match event {
|
||||||
AppEvent::Sessions(Ok(sessions)) => {
|
AppEvent::Sessions(Ok(sessions)) => {
|
||||||
self.sessions = sessions;
|
self.sessions = sessions;
|
||||||
@@ -177,7 +173,7 @@ impl Client {
|
|||||||
&& self.generation.load(Ordering::SeqCst) == generation
|
&& self.generation.load(Ordering::SeqCst) == generation
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_message(&mut self, rsc: &mut DesktopRsc<Self>, message: &str) {
|
fn show_message(&mut self, rsc: &mut StdRsc<Self>, message: &str) {
|
||||||
let widget = placeholder(rsc, message);
|
let widget = placeholder(rsc, message);
|
||||||
(self.transcript_ptr)(rsc).set(widget);
|
(self.transcript_ptr)(rsc).set(widget);
|
||||||
}
|
}
|
||||||
@@ -191,7 +187,7 @@ impl Client {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rebuild_list(&mut self, rsc: &mut DesktopRsc<Self>) {
|
fn rebuild_list(&mut self, rsc: &mut StdRsc<Self>) {
|
||||||
let list = Span::empty(Dir::DOWN).gap(2).add(rsc);
|
let list = Span::empty(Dir::DOWN).gap(2).add(rsc);
|
||||||
for session in &self.sessions {
|
for session in &self.sessions {
|
||||||
let selected = self.selected.as_deref() == Some(session.id.as_str());
|
let selected = self.selected.as_deref() == Some(session.id.as_str());
|
||||||
@@ -205,7 +201,7 @@ impl Client {
|
|||||||
(self.list_ptr)(rsc).set(tree);
|
(self.list_ptr)(rsc).set(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_session(&mut self, rsc: &mut DesktopRsc<Self>, session_id: String) {
|
fn select_session(&mut self, rsc: &mut StdRsc<Self>, session_id: String) {
|
||||||
let generation = self.generation.fetch_add(1, Ordering::SeqCst) + 1;
|
let generation = self.generation.fetch_add(1, Ordering::SeqCst) + 1;
|
||||||
self.selected = Some(session_id.clone());
|
self.selected = Some(session_id.clone());
|
||||||
self.items.clear();
|
self.items.clear();
|
||||||
@@ -270,7 +266,7 @@ impl Client {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rebuild_transcript(&mut self, rsc: &mut DesktopRsc<Self>) {
|
fn rebuild_transcript(&mut self, rsc: &mut StdRsc<Self>) {
|
||||||
let in_progress = self
|
let in_progress = self
|
||||||
.screen
|
.screen
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -299,11 +295,7 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn session_row(
|
fn session_row(rsc: &mut StdRsc<Client>, session: &SessionSummary, selected: bool) -> StrongWidget {
|
||||||
rsc: &mut DesktopRsc<Client>,
|
|
||||||
session: &SessionSummary,
|
|
||||||
selected: bool,
|
|
||||||
) -> StrongWidget {
|
|
||||||
let bg = if selected {
|
let bg = if selected {
|
||||||
Srgba8::rgb(58, 90, 138)
|
Srgba8::rgb(58, 90, 138)
|
||||||
} else {
|
} else {
|
||||||
@@ -319,7 +311,7 @@ fn session_row(
|
|||||||
.background(rect(bg))
|
.background(rect(bg))
|
||||||
.on(
|
.on(
|
||||||
CursorSense::click(),
|
CursorSense::click(),
|
||||||
move |ctx, rsc: &mut DesktopRsc<Client>| {
|
move |ctx, rsc: &mut StdRsc<Client>| {
|
||||||
ctx.state.select_session(rsc, id.clone());
|
ctx.state.select_session(rsc, id.clone());
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -327,7 +319,7 @@ fn session_row(
|
|||||||
.any()
|
.any()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn placeholder(rsc: &mut DesktopRsc<Client>, message: &str) -> StrongWidget {
|
fn placeholder(rsc: &mut StdRsc<Client>, message: &str) -> StrongWidget {
|
||||||
wtext(message.to_string())
|
wtext(message.to_string())
|
||||||
.color(PaintId::WHITE)
|
.color(PaintId::WHITE)
|
||||||
.wrap(true)
|
.wrap(true)
|
||||||
|
|||||||
+5
-3
@@ -13,10 +13,12 @@ open work and measured constraints that are expensive to rediscover.
|
|||||||
Platform services are exposed to shared UI through small traits.
|
Platform services are exposed to shared UI through small traits.
|
||||||
- `iris/` is only a UI framework. Session, transcript, server, setup, and
|
- `iris/` is only a UI framework. Session, transcript, server, setup, and
|
||||||
product styling concepts never belong there.
|
product styling concepts never belong there.
|
||||||
- `iris/src/rsc` groups resources carried by or installed through `AppRsc`:
|
- `iris/src/rsc` groups resources carried by or installed through `StdRsc`:
|
||||||
attributes, events, overlays, pointer sensing/input, tasks, and per-widget
|
attributes, events, overlays, pointer sensing/input, tasks, and per-widget
|
||||||
state. `widget/` is reserved for concrete retained widgets. Public paths
|
state. It is the standard bundle used by Iris's hosts, not a requirement;
|
||||||
such as `iris::sense` remain aliases for readability.
|
shared widgets depend on its narrow resource traits so a custom bundle can
|
||||||
|
implement only what it needs. `widget/` is reserved for concrete retained
|
||||||
|
widgets. Public paths such as `iris::sense` remain aliases for readability.
|
||||||
- Phone and desktop layouts may differ. Their component implementations,
|
- Phone and desktop layouts may differ. Their component implementations,
|
||||||
colors, spacing, text styles, gestures, folding, and network behavior do
|
colors, spacing, text styles, gestures, folding, and network behavior do
|
||||||
not.
|
not.
|
||||||
|
|||||||
@@ -13,15 +13,11 @@ struct State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DesktopAppState for State {
|
impl DesktopAppState for State {
|
||||||
fn new(
|
fn new(mut ui_state: DesktopUiState, rsc: &mut StdRsc<Self>, _: Proxy<Self::Event>) -> Self {
|
||||||
mut ui_state: DesktopUiState,
|
|
||||||
rsc: &mut DesktopRsc<Self>,
|
|
||||||
_: Proxy<Self::Event>,
|
|
||||||
) -> Self {
|
|
||||||
let mut span = Span::empty(Dir::DOWN);
|
let mut span = Span::empty(Dir::DOWN);
|
||||||
for _ in 0..ROWS {
|
for _ in 0..ROWS {
|
||||||
let img = image::DynamicImage::new_rgba8(32, 32);
|
let img = image::DynamicImage::new_rgba8(32, 32);
|
||||||
let widget = image::<DesktopRsc<Self>>(img)(rsc);
|
let widget = image::<StdRsc<Self>>(img)(rsc);
|
||||||
let widget = rsc.ui.widgets.add_strong(widget);
|
let widget = rsc.ui.widgets.add_strong(widget);
|
||||||
span.push(widget.any());
|
span.push(widget.any());
|
||||||
}
|
}
|
||||||
@@ -40,7 +36,7 @@ impl DesktopAppState for State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn window_event(&mut self, event: winit::event::WindowEvent, rsc: &mut DesktopRsc<Self>) {
|
fn window_event(&mut self, event: winit::event::WindowEvent, rsc: &mut StdRsc<Self>) {
|
||||||
if !matches!(event, winit::event::WindowEvent::RedrawRequested) {
|
if !matches!(event, winit::event::WindowEvent::RedrawRequested) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -53,7 +49,7 @@ impl DesktopAppState for State {
|
|||||||
if self.frame == SETTLE_FRAMES && !self.appended {
|
if self.frame == SETTLE_FRAMES && !self.appended {
|
||||||
self.appended = true;
|
self.appended = true;
|
||||||
let img = image::DynamicImage::new_rgba8(32, 32);
|
let img = image::DynamicImage::new_rgba8(32, 32);
|
||||||
let widget = image::<DesktopRsc<Self>>(img)(rsc);
|
let widget = image::<StdRsc<Self>>(img)(rsc);
|
||||||
let widget = rsc.ui.widgets.add_strong(widget);
|
let widget = rsc.ui.widgets.add_strong(widget);
|
||||||
rsc.ui
|
rsc.ui
|
||||||
.widgets
|
.widgets
|
||||||
|
|||||||
@@ -63,11 +63,7 @@ impl DesktopAppState for State {
|
|||||||
WindowAttributes::default().with_inner_size(LogicalSize::new(420.0, 900.0))
|
WindowAttributes::default().with_inner_size(LogicalSize::new(420.0, 900.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(mut ui_state: DesktopUiState, rsc: &mut StdRsc<Self>, _: Proxy<Self::Event>) -> Self {
|
||||||
mut ui_state: DesktopUiState,
|
|
||||||
rsc: &mut DesktopRsc<Self>,
|
|
||||||
_: Proxy<Self::Event>,
|
|
||||||
) -> Self {
|
|
||||||
let mut list = LazySpan::new(Dir::DOWN, Pin::End);
|
let mut list = LazySpan::new(Dir::DOWN, Pin::End);
|
||||||
for i in 0..ROWS {
|
for i in 0..ROWS {
|
||||||
let row = build_row(rsc, i);
|
let row = build_row(rsc, i);
|
||||||
|
|||||||
@@ -10,11 +10,7 @@ struct State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DesktopAppState for State {
|
impl DesktopAppState for State {
|
||||||
fn new(
|
fn new(mut ui_state: DesktopUiState, rsc: &mut StdRsc<Self>, _: Proxy<Self::Event>) -> Self {
|
||||||
mut ui_state: DesktopUiState,
|
|
||||||
rsc: &mut DesktopRsc<Self>,
|
|
||||||
_: Proxy<Self::Event>,
|
|
||||||
) -> Self {
|
|
||||||
rect(PaintId::RED).set_root(rsc, &mut ui_state);
|
rect(PaintId::RED).set_root(rsc, &mut ui_state);
|
||||||
Self { ui_state }
|
Self { ui_state }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,11 +12,7 @@ pub struct Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DesktopAppState for Client {
|
impl DesktopAppState for Client {
|
||||||
fn new(
|
fn new(mut ui_state: DesktopUiState, rsc: &mut StdRsc<Self>, _: Proxy<Self::Event>) -> Self {
|
||||||
mut ui_state: DesktopUiState,
|
|
||||||
rsc: &mut DesktopRsc<Self>,
|
|
||||||
_: Proxy<Self::Event>,
|
|
||||||
) -> Self {
|
|
||||||
let widgets = tabs_ui::build(rsc, &mut ui_state);
|
let widgets = tabs_ui::build(rsc, &mut ui_state);
|
||||||
Self {
|
Self {
|
||||||
ui_state,
|
ui_state,
|
||||||
@@ -24,7 +20,7 @@ impl DesktopAppState for Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn window_event(&mut self, _: WindowEvent, rsc: &mut DesktopRsc<Self>) {
|
fn window_event(&mut self, _: WindowEvent, rsc: &mut StdRsc<Self>) {
|
||||||
let render_state = rsc.ui.render_state();
|
let render_state = rsc.ui.render_state();
|
||||||
let new = format!(
|
let new = format!(
|
||||||
"widgets: {}\nactive: {}\nviews: {}",
|
"widgets: {}\nactive: {}\nviews: {}",
|
||||||
|
|||||||
@@ -11,11 +11,7 @@ struct State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DesktopAppState for State {
|
impl DesktopAppState for State {
|
||||||
fn new(
|
fn new(mut ui_state: DesktopUiState, rsc: &mut StdRsc<Self>, _: Proxy<Self::Event>) -> Self {
|
||||||
mut ui_state: DesktopUiState,
|
|
||||||
rsc: &mut DesktopRsc<Self>,
|
|
||||||
_: Proxy<Self::Event>,
|
|
||||||
) -> Self {
|
|
||||||
let rect = rect(PaintId::RED).add(rsc);
|
let rect = rect(PaintId::RED).add(rsc);
|
||||||
rect.task_on(CursorSense::click(), async move |mut ctx| {
|
rect.task_on(CursorSense::click(), async move |mut ctx| {
|
||||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ struct State {
|
|||||||
ui_state: DesktopUiState,
|
ui_state: DesktopUiState,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Rsc = DesktopRsc<State>;
|
type Rsc = StdRsc<State>;
|
||||||
|
|
||||||
#[derive(Clone, Copy, WidgetView)]
|
#[derive(Clone, Copy, WidgetView)]
|
||||||
struct Test {
|
struct Test {
|
||||||
@@ -36,11 +36,7 @@ impl Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DesktopAppState for State {
|
impl DesktopAppState for State {
|
||||||
fn new(
|
fn new(mut ui_state: DesktopUiState, rsc: &mut StdRsc<Self>, _: Proxy<Self::Event>) -> Self {
|
||||||
mut ui_state: DesktopUiState,
|
|
||||||
rsc: &mut DesktopRsc<Self>,
|
|
||||||
_: Proxy<Self::Event>,
|
|
||||||
) -> Self {
|
|
||||||
let test = Test::new(rsc);
|
let test = Test::new(rsc);
|
||||||
|
|
||||||
test.on(CursorSense::click(), move |_, rsc| {
|
test.on(CursorSense::click(), move |_, rsc| {
|
||||||
|
|||||||
+69
-14
@@ -103,31 +103,72 @@ pub fn widget_trait(input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
#[proc_macro_derive(DesktopUiState, attributes(desktop_ui_state))]
|
#[proc_macro_derive(DesktopUiState, attributes(desktop_ui_state))]
|
||||||
pub fn derive_desktop_ui_state(input: TokenStream) -> TokenStream {
|
pub fn derive_desktop_ui_state(input: TokenStream) -> TokenStream {
|
||||||
let mut output = proc_macro2::TokenStream::new();
|
|
||||||
|
|
||||||
let state: ItemStruct = parse_macro_input!(input);
|
let state: ItemStruct = parse_macro_input!(input);
|
||||||
|
derive_ui_state(
|
||||||
|
state,
|
||||||
|
UiStateDerive {
|
||||||
|
module: "desktop",
|
||||||
|
state_type: "DesktopUiState",
|
||||||
|
state_trait: "HasDesktopUiState",
|
||||||
|
field_attr: "desktop_ui_state",
|
||||||
|
get: "desktop_state",
|
||||||
|
get_mut: "desktop_state_mut",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(AndroidUiState, attributes(android_ui_state))]
|
||||||
|
pub fn derive_android_ui_state(input: TokenStream) -> TokenStream {
|
||||||
|
let state: ItemStruct = parse_macro_input!(input);
|
||||||
|
derive_ui_state(
|
||||||
|
state,
|
||||||
|
UiStateDerive {
|
||||||
|
module: "android",
|
||||||
|
state_type: "AndroidUiState",
|
||||||
|
state_trait: "HasAndroidUiState",
|
||||||
|
field_attr: "android_ui_state",
|
||||||
|
get: "android_state",
|
||||||
|
get_mut: "android_state_mut",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct UiStateDerive {
|
||||||
|
module: &'static str,
|
||||||
|
state_type: &'static str,
|
||||||
|
state_trait: &'static str,
|
||||||
|
field_attr: &'static str,
|
||||||
|
get: &'static str,
|
||||||
|
get_mut: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn derive_ui_state(state: ItemStruct, names: UiStateDerive) -> TokenStream {
|
||||||
|
let UiStateDerive {
|
||||||
|
module,
|
||||||
|
state_type,
|
||||||
|
state_trait,
|
||||||
|
field_attr,
|
||||||
|
get,
|
||||||
|
get_mut,
|
||||||
|
} = names;
|
||||||
|
let mut output = proc_macro2::TokenStream::new();
|
||||||
let mut found_attr = false;
|
let mut found_attr = false;
|
||||||
let mut state_field = None;
|
let mut state_field = None;
|
||||||
for field in &state.fields {
|
for field in &state.fields {
|
||||||
if !found_attr
|
if !found_attr
|
||||||
&& let Type::Path(path) = &field.ty
|
&& let Type::Path(path) = &field.ty
|
||||||
&& path.path.is_ident("DesktopUiState")
|
&& path.path.is_ident(state_type)
|
||||||
{
|
{
|
||||||
state_field = Some(field);
|
state_field = Some(field);
|
||||||
}
|
}
|
||||||
let Some(attr) = field
|
let Some(attr) = field.attrs.iter().find(|a| a.path().is_ident(field_attr)) else {
|
||||||
.attrs
|
|
||||||
.iter()
|
|
||||||
.find(|a| a.path().is_ident("desktop_ui_state"))
|
|
||||||
else {
|
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if found_attr {
|
if found_attr {
|
||||||
output.extend(
|
output.extend(
|
||||||
Error::new(
|
Error::new(
|
||||||
attr.span(),
|
attr.span(),
|
||||||
"cannot have more than one desktop_ui_state attribute",
|
format!("cannot have more than one {field_attr} attribute"),
|
||||||
)
|
)
|
||||||
.into_compile_error(),
|
.into_compile_error(),
|
||||||
);
|
);
|
||||||
@@ -138,18 +179,32 @@ pub fn derive_desktop_ui_state(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
let Some(field) = state_field else {
|
let Some(field) = state_field else {
|
||||||
output.extend(
|
output.extend(
|
||||||
Error::new(state.ident.span(), "no DesktopUiState field found").into_compile_error(),
|
Error::new(state.ident.span(), format!("no {state_type} field found"))
|
||||||
|
.into_compile_error(),
|
||||||
);
|
);
|
||||||
return output.into();
|
return output.into();
|
||||||
};
|
};
|
||||||
let sname = &state.ident;
|
let sname = &state.ident;
|
||||||
let fname = field.ident.as_ref().unwrap();
|
let Some(fname) = field.ident.as_ref() else {
|
||||||
|
return Error::new(
|
||||||
|
field.span(),
|
||||||
|
format!("the {state_type} field must be named"),
|
||||||
|
)
|
||||||
|
.into_compile_error()
|
||||||
|
.into();
|
||||||
|
};
|
||||||
|
let module = Ident::new(module, sname.span());
|
||||||
|
let state_type = Ident::new(state_type, sname.span());
|
||||||
|
let state_trait = Ident::new(state_trait, sname.span());
|
||||||
|
let get = Ident::new(get, sname.span());
|
||||||
|
let get_mut = Ident::new(get_mut, sname.span());
|
||||||
|
let (impl_generics, type_generics, where_clause) = state.generics.split_for_impl();
|
||||||
output.extend(quote! {
|
output.extend(quote! {
|
||||||
impl iris::desktop::HasDesktopUiState for #sname {
|
impl #impl_generics iris::#module::#state_trait for #sname #type_generics #where_clause {
|
||||||
fn desktop_state(&self) -> &iris::desktop::DesktopUiState {
|
fn #get(&self) -> &iris::#module::#state_type {
|
||||||
&self.#fname
|
&self.#fname
|
||||||
}
|
}
|
||||||
fn desktop_state_mut(&mut self) -> &mut iris::desktop::DesktopUiState {
|
fn #get_mut(&mut self) -> &mut iris::#module::#state_type {
|
||||||
&mut self.#fname
|
&mut self.#fname
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use android_view::{jni::JNIEnv, ndk::event::Keycode};
|
use android_view::{jni::JNIEnv, ndk::event::Keycode};
|
||||||
|
|
||||||
use super::view::{AndroidAppState, AndroidRsc};
|
use super::view::AndroidAppState;
|
||||||
|
|
||||||
/// Hardware/synthesized key handling for the field that currently has
|
/// Hardware/synthesized key handling for the field that currently has
|
||||||
/// focus. Most typing on Android goes through the IME's `InputConnection`
|
/// focus. Most typing on Android goes through the IME's `InputConnection`
|
||||||
@@ -10,7 +10,7 @@ use super::view::{AndroidAppState, AndroidRsc};
|
|||||||
/// the arrow keys on a physical keyboard) plus whatever `unicode_char`
|
/// the arrow keys on a physical keyboard) plus whatever `unicode_char`
|
||||||
/// reports for a plain key press. Returns whether anything used the event.
|
/// reports for a plain key press. Returns whether anything used the event.
|
||||||
pub(super) fn on_key<'local, State: AndroidAppState>(
|
pub(super) fn on_key<'local, State: AndroidAppState>(
|
||||||
rsc: &mut AndroidRsc<State>,
|
rsc: &mut StdRsc<State>,
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
env: &mut JNIEnv<'local>,
|
env: &mut JNIEnv<'local>,
|
||||||
key_code: Keycode,
|
key_code: Keycode,
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ mod view;
|
|||||||
pub use insets::Insets;
|
pub use insets::Insets;
|
||||||
pub use render::AndroidRenderer;
|
pub use render::AndroidRenderer;
|
||||||
pub use view::{
|
pub use view::{
|
||||||
AndroidAppState, AndroidRsc, AndroidUiState, HasAndroidUiState, IrisViewPeer, WindowInsets,
|
AndroidAppState, AndroidUiState, HasAndroidUiState, IrisViewPeer, WindowInsets, new_peer,
|
||||||
new_peer,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Registers the extra native methods this backend needs beyond what
|
/// Registers the extra native methods this backend needs beyond what
|
||||||
|
|||||||
@@ -89,8 +89,8 @@ impl AndroidUiState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<State: 'static> HasRoot<AndroidRsc<State>> for AndroidUiState {
|
impl<State: 'static> HasRoot<StdRsc<State>> for AndroidUiState {
|
||||||
fn set_root(&mut self, rsc: &mut AndroidRsc<State>, root: StrongWidget) {
|
fn set_root(&mut self, rsc: &mut StdRsc<State>, root: StrongWidget) {
|
||||||
self.root = Some(crate::overlay::default_overlay_root(rsc, root));
|
self.root = Some(crate::overlay::default_overlay_root(rsc, root));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,15 +101,15 @@ pub trait HasAndroidUiState: Sized + 'static {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait AndroidAppState: HasAndroidUiState {
|
pub trait AndroidAppState: HasAndroidUiState {
|
||||||
fn new(ui_state: AndroidUiState, rsc: &mut AndroidRsc<Self>) -> Self;
|
fn new(ui_state: AndroidUiState, rsc: &mut StdRsc<Self>) -> Self;
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn back_pressed(&mut self, rsc: &mut AndroidRsc<Self>) -> bool {
|
fn back_pressed(&mut self, rsc: &mut StdRsc<Self>) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn platform_ready(&mut self, rsc: &mut AndroidRsc<Self>, vm: JavaVM, view: GlobalRef) {}
|
fn platform_ready(&mut self, rsc: &mut StdRsc<Self>, vm: JavaVM, view: GlobalRef) {}
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn on_insets_changed(&mut self, rsc: &mut AndroidRsc<Self>, insets: WindowInsets) {}
|
fn on_insets_changed(&mut self, rsc: &mut StdRsc<Self>, insets: WindowInsets) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Widget-facing insets in physical pixels, decoupled from JNI's integer shape.
|
/// Widget-facing insets in physical pixels, decoupled from JNI's integer shape.
|
||||||
@@ -140,15 +140,13 @@ impl WindowInsets {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type AndroidRsc<State> = AppRsc<State>;
|
|
||||||
|
|
||||||
/// The `ViewPeer` android-view dispatches every callback to. One per
|
/// The `ViewPeer` android-view dispatches every callback to. One per
|
||||||
/// `RustView` instance; `new_peer` (below) builds it and hands the id to
|
/// `RustView` instance; `new_peer` (below) builds it and hands the id to
|
||||||
/// Java the same way android-view's own demo does.
|
/// Java the same way android-view's own demo does.
|
||||||
pub struct IrisViewPeer<State: AndroidAppState> {
|
pub struct IrisViewPeer<State: AndroidAppState> {
|
||||||
pub(super) rsc: AndroidRsc<State>,
|
pub(super) rsc: StdRsc<State>,
|
||||||
pub(super) state: State,
|
pub(super) state: State,
|
||||||
task_recv: TaskMsgReceiver<AndroidRsc<State>>,
|
task_recv: TaskMsgReceiver<StdRsc<State>>,
|
||||||
/// Converts input and Choreographer timestamps onto one monotonic clock.
|
/// Converts input and Choreographer timestamps onto one monotonic clock.
|
||||||
device_clock: Option<DeviceClock>,
|
device_clock: Option<DeviceClock>,
|
||||||
}
|
}
|
||||||
@@ -812,7 +810,7 @@ pub fn new_peer<'local, State: AndroidAppState>(
|
|||||||
let vm = env.get_java_vm().unwrap();
|
let vm = env.get_java_vm().unwrap();
|
||||||
let global_view = env.new_global_ref(&view.0).unwrap();
|
let global_view = env.new_global_ref(&view.0).unwrap();
|
||||||
let redraw: Arc<dyn RequestRedraw> = Arc::new(AndroidRedrawHandle::new(vm, global_view));
|
let redraw: Arc<dyn RequestRedraw> = Arc::new(AndroidRedrawHandle::new(vm, global_view));
|
||||||
let (mut rsc, task_recv) = AppRsc::new(redraw);
|
let (mut rsc, task_recv) = StdRsc::new(redraw);
|
||||||
rsc.ui.set_density(content_scale);
|
rsc.ui.set_density(content_scale);
|
||||||
let shared = Rc::new(RefCell::new(Shared::default()));
|
let shared = Rc::new(RefCell::new(Shared::default()));
|
||||||
let ui_state = AndroidUiState::new(shared.clone(), content_scale);
|
let ui_state = AndroidUiState::new(shared.clone(), content_scale);
|
||||||
|
|||||||
+9
-12
@@ -50,8 +50,8 @@ pub struct DesktopUiState {
|
|||||||
pub access: AccessTree,
|
pub access: AccessTree,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<State: 'static> HasRoot<DesktopRsc<State>> for DesktopUiState {
|
impl<State: 'static> HasRoot<StdRsc<State>> for DesktopUiState {
|
||||||
fn set_root(&mut self, rsc: &mut DesktopRsc<State>, root: StrongWidget) {
|
fn set_root(&mut self, rsc: &mut StdRsc<State>, root: StrongWidget) {
|
||||||
self.root = Some(crate::overlay::default_overlay_root(rsc, root));
|
self.root = Some(crate::overlay::default_overlay_root(rsc, root));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,25 +81,22 @@ pub trait HasDesktopUiState: Sized + 'static {
|
|||||||
|
|
||||||
pub trait DesktopAppState: HasDesktopUiState {
|
pub trait DesktopAppState: HasDesktopUiState {
|
||||||
type Event = ();
|
type Event = ();
|
||||||
fn new(ui_state: DesktopUiState, rsc: &mut DesktopRsc<Self>, proxy: Proxy<Self::Event>)
|
fn new(ui_state: DesktopUiState, rsc: &mut StdRsc<Self>, proxy: Proxy<Self::Event>) -> Self;
|
||||||
-> Self;
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn event(&mut self, event: Self::Event, rsc: &mut DesktopRsc<Self>) {}
|
fn event(&mut self, event: Self::Event, rsc: &mut StdRsc<Self>) {}
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn exit(&mut self, rsc: &mut DesktopRsc<Self>) {}
|
fn exit(&mut self, rsc: &mut StdRsc<Self>) {}
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn window_event(&mut self, event: WindowEvent, rsc: &mut DesktopRsc<Self>) {}
|
fn window_event(&mut self, event: WindowEvent, rsc: &mut StdRsc<Self>) {}
|
||||||
fn window_attributes() -> WindowAttributes {
|
fn window_attributes() -> WindowAttributes {
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DesktopRsc<State> = AppRsc<State>;
|
|
||||||
|
|
||||||
pub struct DesktopApp<State: DesktopAppState> {
|
pub struct DesktopApp<State: DesktopAppState> {
|
||||||
rsc: DesktopRsc<State>,
|
rsc: StdRsc<State>,
|
||||||
state: State,
|
state: State,
|
||||||
task_recv: TaskMsgReceiver<DesktopRsc<State>>,
|
task_recv: TaskMsgReceiver<StdRsc<State>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<State: DesktopAppState> AppState for DesktopApp<State> {
|
impl<State: DesktopAppState> AppState for DesktopApp<State> {
|
||||||
@@ -118,7 +115,7 @@ impl<State: DesktopAppState> AppState for DesktopApp<State> {
|
|||||||
);
|
);
|
||||||
window.set_visible(true);
|
window.set_visible(true);
|
||||||
let desktop_state = DesktopUiState::new(window, access_adapter);
|
let desktop_state = DesktopUiState::new(window, access_adapter);
|
||||||
let (mut rsc, task_recv) = AppRsc::new(desktop_state.window.clone());
|
let (mut rsc, task_recv) = StdRsc::new(desktop_state.window.clone());
|
||||||
// Set before building widgets so the first text shape uses the right density.
|
// Set before building widgets so the first text shape uses the right density.
|
||||||
let scale = content_scale(desktop_state.window.as_ref());
|
let scale = content_scale(desktop_state.window.as_ref());
|
||||||
rsc.ui.set_density(scale);
|
rsc.ui.set_density(scale);
|
||||||
|
|||||||
+5
-7
@@ -134,8 +134,8 @@ impl HarnessState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasRoot<HarnessRsc> for HarnessState {
|
impl HasRoot<StdRsc<HarnessState>> for HarnessState {
|
||||||
fn set_root(&mut self, rsc: &mut HarnessRsc, root: StrongWidget) {
|
fn set_root(&mut self, rsc: &mut StdRsc<HarnessState>, root: StrongWidget) {
|
||||||
self.root = Some(crate::overlay::default_overlay_root(rsc, root));
|
self.root = Some(crate::overlay::default_overlay_root(rsc, root));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,14 +163,12 @@ impl OpenUrl for HarnessState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type HarnessRsc = AppRsc<HarnessState>;
|
|
||||||
|
|
||||||
/// A screen running with no window: the widget tree, the frame loop and
|
/// A screen running with no window: the widget tree, the frame loop and
|
||||||
/// the pointer, all advanced by the caller. See the module doc.
|
/// the pointer, all advanced by the caller. See the module doc.
|
||||||
pub struct Harness {
|
pub struct Harness {
|
||||||
pub rsc: HarnessRsc,
|
pub rsc: StdRsc<HarnessState>,
|
||||||
pub state: HarnessState,
|
pub state: HarnessState,
|
||||||
task_recv: TaskMsgReceiver<HarnessRsc>,
|
task_recv: TaskMsgReceiver<StdRsc<HarnessState>>,
|
||||||
redraws: Arc<RedrawCounter>,
|
redraws: Arc<RedrawCounter>,
|
||||||
cursor: CursorState,
|
cursor: CursorState,
|
||||||
base: Instant,
|
base: Instant,
|
||||||
@@ -185,7 +183,7 @@ impl Harness {
|
|||||||
/// `PHONE_SCALE`.
|
/// `PHONE_SCALE`.
|
||||||
pub fn new(size: Vec2, density: f32) -> Self {
|
pub fn new(size: Vec2, density: f32) -> Self {
|
||||||
let redraws = Arc::new(RedrawCounter::default());
|
let redraws = Arc::new(RedrawCounter::default());
|
||||||
let (mut rsc, task_recv) = AppRsc::new(redraws.clone());
|
let (mut rsc, task_recv) = StdRsc::new(redraws.clone());
|
||||||
rsc.ui.set_density(density);
|
rsc.ui.set_density(density);
|
||||||
rsc.ui.resize(size);
|
rsc.ui.resize(size);
|
||||||
Self {
|
Self {
|
||||||
|
|||||||
+14
-11
@@ -1,4 +1,4 @@
|
|||||||
//! Host-independent resources carried by [`AppRsc`].
|
//! Host-independent resources carried by [`StdRsc`].
|
||||||
|
|
||||||
pub mod attr;
|
pub mod attr;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
@@ -20,8 +20,11 @@ pub use task::*;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// Resources shared by every Iris host.
|
/// Iris's standard resource bundle.
|
||||||
pub struct AppRsc<State: 'static> {
|
///
|
||||||
|
/// Built-in hosts use this bundle, but widgets should depend on the narrow
|
||||||
|
/// resource traits they need so applications can supply a different bundle.
|
||||||
|
pub struct StdRsc<State: 'static> {
|
||||||
pub ui: Ui,
|
pub ui: Ui,
|
||||||
pub events: EventManager<Self>,
|
pub events: EventManager<Self>,
|
||||||
pub tasks: Tasks<Self>,
|
pub tasks: Tasks<Self>,
|
||||||
@@ -29,7 +32,7 @@ pub struct AppRsc<State: 'static> {
|
|||||||
_state: std::marker::PhantomData<State>,
|
_state: std::marker::PhantomData<State>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<State> AppRsc<State> {
|
impl<State> StdRsc<State> {
|
||||||
pub(crate) fn new(redraw: Arc<dyn RequestRedraw>) -> (Self, TaskMsgReceiver<Self>) {
|
pub(crate) fn new(redraw: Arc<dyn RequestRedraw>) -> (Self, TaskMsgReceiver<Self>) {
|
||||||
let (tasks, receiver) = Tasks::init(redraw);
|
let (tasks, receiver) = Tasks::init(redraw);
|
||||||
(
|
(
|
||||||
@@ -49,7 +52,7 @@ impl<State> AppRsc<State> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<State> UiRsc for AppRsc<State> {
|
impl<State> UiRsc for StdRsc<State> {
|
||||||
fn ui(&self) -> &Ui {
|
fn ui(&self) -> &Ui {
|
||||||
&self.ui
|
&self.ui
|
||||||
}
|
}
|
||||||
@@ -72,11 +75,11 @@ impl<State> UiRsc for AppRsc<State> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<State> HasState for AppRsc<State> {
|
impl<State> HasState for StdRsc<State> {
|
||||||
type State = State;
|
type State = State;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<State> HasEvents for AppRsc<State> {
|
impl<State> HasEvents for StdRsc<State> {
|
||||||
fn events(&self) -> &EventManager<Self> {
|
fn events(&self) -> &EventManager<Self> {
|
||||||
&self.events
|
&self.events
|
||||||
}
|
}
|
||||||
@@ -86,13 +89,13 @@ impl<State> HasEvents for AppRsc<State> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<State> HasTasks for AppRsc<State> {
|
impl<State> HasTasks for StdRsc<State> {
|
||||||
fn tasks_mut(&mut self) -> &mut Tasks<Self> {
|
fn tasks_mut(&mut self) -> &mut Tasks<Self> {
|
||||||
&mut self.tasks
|
&mut self.tasks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<State> HasWidgetState for AppRsc<State> {
|
impl<State> HasWidgetState for StdRsc<State> {
|
||||||
fn widget_state(&self) -> &WidgetState {
|
fn widget_state(&self) -> &WidgetState {
|
||||||
&self.state
|
&self.state
|
||||||
}
|
}
|
||||||
@@ -102,7 +105,7 @@ impl<State> HasWidgetState for AppRsc<State> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<State, I: RscIdx<AppRsc<State>>> std::ops::Index<I> for AppRsc<State> {
|
impl<State, I: RscIdx<StdRsc<State>>> std::ops::Index<I> for StdRsc<State> {
|
||||||
type Output = I::Output;
|
type Output = I::Output;
|
||||||
|
|
||||||
fn index(&self, index: I) -> &Self::Output {
|
fn index(&self, index: I) -> &Self::Output {
|
||||||
@@ -110,7 +113,7 @@ impl<State, I: RscIdx<AppRsc<State>>> std::ops::Index<I> for AppRsc<State> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<State, I: RscIdx<AppRsc<State>>> std::ops::IndexMut<I> for AppRsc<State> {
|
impl<State, I: RscIdx<StdRsc<State>>> std::ops::IndexMut<I> for StdRsc<State> {
|
||||||
fn index_mut(&mut self, index: I) -> &mut Self::Output {
|
fn index_mut(&mut self, index: I) -> &mut Self::Output {
|
||||||
index.get_mut(self)
|
index.get_mut(self)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -525,13 +525,13 @@ fn open_stackable_at<Rsc: HasEvents>(
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::harness::{Harness, HarnessRsc, TouchAction};
|
use crate::harness::{Harness, HarnessState, TouchAction};
|
||||||
use std::{cell::Cell, rc::Rc};
|
use std::{cell::Cell, rc::Rc};
|
||||||
|
|
||||||
struct EscapeCounter(Rc<Cell<usize>>);
|
struct EscapeCounter(Rc<Cell<usize>>);
|
||||||
|
|
||||||
impl Controller<HarnessRsc> for EscapeCounter {
|
impl Controller<StdRsc<HarnessState>> for EscapeCounter {
|
||||||
fn command(&mut self, command: Command, _rsc: &mut HarnessRsc) -> CommandResult {
|
fn command(&mut self, command: Command, _rsc: &mut StdRsc<HarnessState>) -> CommandResult {
|
||||||
if command == Command::Escape {
|
if command == Command::Escape {
|
||||||
self.0.set(self.0.get() + 1);
|
self.0.set(self.0.get() + 1);
|
||||||
CommandResult::Used
|
CommandResult::Used
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ impl<'a, T: 'static> FnOnce<(&'a mut WidgetState,)> for WeakState<T> {
|
|||||||
/// What `Rsc[weak_handle]` indexes through -- one impl per kind of handle
|
/// What `Rsc[weak_handle]` indexes through -- one impl per kind of handle
|
||||||
/// (a widget, a piece of per-widget state), shared by both backends' `Rsc`
|
/// (a widget, a piece of per-widget state), shared by both backends' `Rsc`
|
||||||
/// types since indexing a widget tree has nothing to do with windowing.
|
/// types since indexing a widget tree has nothing to do with windowing.
|
||||||
/// `AppRsc` supplies the shared `Index`/`IndexMut` implementation; a blanket
|
/// `StdRsc` supplies the shared `Index`/`IndexMut` implementation; a blanket
|
||||||
/// implementation over every possible resource type would conflict.
|
/// implementation over every possible resource type would conflict.
|
||||||
pub trait RscIdx<Rsc> {
|
pub trait RscIdx<Rsc> {
|
||||||
type Output;
|
type Output;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
use iris::{harness::Harness, prelude::*};
|
use iris::{
|
||||||
|
harness::{Harness, HarnessState},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
use pollster::FutureExt;
|
use pollster::FutureExt;
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
use wgpu::TextureFormat;
|
use wgpu::TextureFormat;
|
||||||
@@ -25,7 +28,7 @@ fn solid_paints_and_images_round_trip_through_an_srgb_target() {
|
|||||||
1,
|
1,
|
||||||
image::Rgba([IMAGE.r, IMAGE.g, IMAGE.b, IMAGE.a]),
|
image::Rgba([IMAGE.r, IMAGE.g, IMAGE.b, IMAGE.a]),
|
||||||
));
|
));
|
||||||
let bitmap = image::<iris::harness::HarnessRsc>(bitmap)(&mut harness.rsc);
|
let bitmap = image::<StdRsc<HarnessState>>(bitmap)(&mut harness.rsc);
|
||||||
let root = (rect(solid.clone()).sized((1, 1)), bitmap)
|
let root = (rect(solid.clone()).sized((1, 1)), bitmap)
|
||||||
.span(Dir::RIGHT)
|
.span(Dir::RIGHT)
|
||||||
.add_strong(&mut harness.rsc)
|
.add_strong(&mut harness.rsc)
|
||||||
|
|||||||
Reference in new issue
Block a user