//! Demonstrates use of the ViewDispatcher module. //! //! This app prompts the user for a name then says hello. #![no_main] #![no_std] extern crate alloc; extern crate flipperzero_alloc; extern crate flipperzero_rt; use alloc::boxed::Box; use core::ffi::{c_char, c_void, CStr}; use core::ptr::NonNull; use flipperzero::furi::string::FuriString; use flipperzero_rt::{entry, manifest}; use flipperzero_sys as sys; use flipperzero_sys::furi::UnsafeRecord; manifest!(name = "Rust ViewDispatcher example"); entry!(main); enum AppView { Widget = 0, TextInput = 1, } struct App { name: [c_char; 16], view_dispatcher: NonNull, widget: NonNull, text_input: NonNull, } impl App { pub fn new() -> Box { Box::new(App { name: Default::default(), view_dispatcher: unsafe { NonNull::new_unchecked(sys::view_dispatcher_alloc()) }, widget: unsafe { NonNull::new_unchecked(sys::widget_alloc()) }, text_input: unsafe { NonNull::new_unchecked(sys::text_input_alloc()) }, }) } } impl Drop for App { fn drop(&mut self) { unsafe { sys::view_dispatcher_free(self.view_dispatcher.as_ptr()); sys::widget_free(self.widget.as_ptr()); sys::text_input_free(self.text_input.as_ptr()); } } } pub unsafe extern "C" fn text_input_callback(context: *mut c_void) { let app = context as *mut App; let mut message = FuriString::from("Hello "); message.push_c_str(CStr::from_ptr((*app).name.as_ptr())); sys::widget_add_string_element( (*app).widget.as_ptr(), 128 / 2, 64 / 2, sys::Align_AlignCenter, sys::Align_AlignCenter, sys::Font_FontPrimary, message.as_c_ptr(), ); sys::view_dispatcher_switch_to_view((*app).view_dispatcher.as_ptr(), AppView::Widget as u32); } pub unsafe extern "C" fn navigation_event_callback(context: *mut c_void) -> bool { let view_dispatcher = context as *mut sys::ViewDispatcher; sys::view_dispatcher_stop(view_dispatcher); sys::view_dispatcher_remove_view(view_dispatcher, AppView::Widget as u32); sys::view_dispatcher_remove_view(view_dispatcher, AppView::TextInput as u32); true } fn main(_args: Option<&CStr>) -> i32 { let mut app = App::new(); unsafe { sys::view_dispatcher_enable_queue(app.view_dispatcher.as_ptr()); sys::view_dispatcher_set_event_callback_context( app.view_dispatcher.as_ptr(), app.view_dispatcher.as_ptr() as *mut c_void, ); sys::view_dispatcher_set_navigation_event_callback( app.view_dispatcher.as_ptr(), Some(navigation_event_callback), ); sys::view_dispatcher_add_view( app.view_dispatcher.as_ptr(), AppView::Widget as u32, sys::widget_get_view(app.widget.as_ptr()), ); sys::view_dispatcher_add_view( app.view_dispatcher.as_ptr(), AppView::TextInput as u32, sys::text_input_get_view(app.text_input.as_ptr()), ); } unsafe { let gui = UnsafeRecord::open(c"gui".as_ptr()); sys::view_dispatcher_attach_to_gui( app.view_dispatcher.as_ptr(), gui.as_ptr(), sys::ViewDispatcherType_ViewDispatcherTypeFullscreen, ); sys::text_input_reset(app.text_input.as_ptr()); sys::text_input_set_header_text(app.text_input.as_ptr(), c"Enter your name".as_ptr()); sys::text_input_set_result_callback( app.text_input.as_ptr(), Some(text_input_callback), &*app as *const App as *mut c_void, app.name.as_mut_ptr(), app.name.len(), true, ); sys::view_dispatcher_switch_to_view( app.view_dispatcher.as_ptr(), AppView::TextInput as u32, ); sys::view_dispatcher_run(app.view_dispatcher.as_ptr()); } 0 }