-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathlib.rs
More file actions
108 lines (98 loc) · 3.69 KB
/
Copy pathlib.rs
File metadata and controls
108 lines (98 loc) · 3.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
#![deny(unsafe_op_in_unsafe_fn)]
use android_view::{
jni::{
JNIEnv, JavaVM,
sys::{JNI_VERSION_1_6, JavaVM as RawJavaVM, jint, jlong},
},
*,
};
use masonry::{
core::{ErasedAction, NewWidget, Properties, Widget, WidgetId},
properties::{Padding, types::Length},
theme::default_property_set,
widgets::{Button, ButtonPress, Flex, Label, Portal, TextAction, TextArea, TextInput},
};
use masonry_android::{AppDriver, DriverCtx};
use std::{ffi::c_void, sync::Arc};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
const WIDGET_SPACING: Length = Length::const_px(5.0);
struct Driver {
next_task: String,
}
impl AppDriver for Driver {
fn on_action(&mut self, ctx: &mut DriverCtx<'_>, _widget_id: WidgetId, action: ErasedAction) {
if action.is::<ButtonPress>() {
ctx.render_root().edit_base_layer(|mut root| {
let mut portal = root.downcast::<Portal<Flex>>();
let mut flex = Portal::child_mut(&mut portal);
Flex::add_child(&mut flex, Label::new(self.next_task.clone()).with_auto_id());
let mut first_row = Flex::child_mut(&mut flex, 0).unwrap();
let mut first_row = first_row.downcast::<Flex>();
let mut text_input = Flex::child_mut(&mut first_row, 0).unwrap();
let mut text_input = text_input.downcast::<TextInput>();
let mut text_area = TextInput::text_mut(&mut text_input);
TextArea::reset_text(&mut text_area, "");
});
} else if action.is::<TextAction>() {
let action = action.downcast::<TextAction>().unwrap();
match *action {
TextAction::Changed(new_text) => {
self.next_task = new_text.clone();
}
TextAction::Entered(_) => {}
}
}
}
}
fn make_widget_tree() -> impl Widget {
Portal::new(
Flex::column()
.with_child(NewWidget::new_with_props(
Flex::row()
.with_flex_child(TextInput::new("").with_auto_id(), 1.0)
.with_child(Button::new(NewWidget::new(Label::new("Add task"))).with_auto_id()),
Properties::new().with(Padding::all(WIDGET_SPACING.get())),
))
.with_spacer(WIDGET_SPACING)
.with_auto_id(),
)
}
extern "system" fn new_view_peer<'local>(
mut env: JNIEnv<'local>,
_view: View<'local>,
context: Context<'local>,
) -> jlong {
masonry_android::new_view_peer(
&mut env,
&context,
NewWidget::new(make_widget_tree()).erased(),
Driver {
next_task: String::new(),
},
Arc::new(default_property_set()),
)
}
/// Symbol run at JNI load time.
///
/// # Safety
/// There is no alternative, interacting with JNI is always unsafe at some level.
#[unsafe(no_mangle)]
pub unsafe extern "system" fn JNI_OnLoad(vm: *mut RawJavaVM, _: *mut c_void) -> jint {
// This will try to create a "log" logger, and error because one was already created above
// We therefore ignore the error
// Ideally, we'd only ignore the SetLoggerError, but the only way that's possible is to inspect
// `Debug/Display` on the TryInitError, which is awful.
let _ = tracing_subscriber::registry()
.with(tracing_android_trace::AndroidTraceLayer::new())
.try_init();
let vm = unsafe { JavaVM::from_raw(vm) }.unwrap();
let mut env = vm.get_env().unwrap();
register_view_class(
&mut env,
"org/linebender/android/masonrydemo/DemoView",
new_view_peer,
);
JNI_VERSION_1_6
}