| use crate::APP; |
| use failure::Error; |
| use fidl::encoding::OutOfLine; |
| use fidl::endpoints::create_endpoints; |
| use fidl_fuchsia_math::{InsetF, SizeF}; |
| use fidl_fuchsia_textinputmod::{ |
| TextInputModMarker, TextInputModProxy, TextInputModReceiverMarker, TextInputModReceiverRequest, |
| }; |
| use fidl_fuchsia_ui_app::ViewProviderMarker; |
| use fidl_fuchsia_ui_gfx::{ExportToken, ImportToken}; |
| use fidl_fuchsia_ui_viewsv1::{CustomFocusBehavior, ViewLayout, ViewProperties}; |
| use fuchsia_app::client::{App, Launcher}; |
| use fuchsia_async as fasync; |
| use fuchsia_scenic::{EntityNode, ImportNode, SessionPtr}; |
| use fuchsia_zircon as zx; |
| use futures::{TryFutureExt, TryStreamExt}; |
| |
| pub struct AskBox { |
| _app: App, |
| key: u32, |
| pub host_node: EntityNode, |
| pub text_input_mod: TextInputModProxy, |
| } |
| |
| impl AskBox { |
| fn setup_view( |
| app: &App, |
| key: u32, |
| session: &SessionPtr, |
| view_container: &fidl_fuchsia_ui_viewsv1::ViewContainerProxy, |
| import_node: &ImportNode, |
| ) -> Result<EntityNode, Error> { |
| let view_provider = app.connect_to_service(ViewProviderMarker)?; |
| let (import, export) = zx::EventPair::create()?; |
| let view_holder_token = ImportToken { value: import }; |
| let view_token = ExportToken { value: export }; |
| view_provider.create_view(view_token.value, None, None)?; |
| let host_node = EntityNode::new(session.clone()); |
| let host_import_token = host_node.export_as_request(); |
| |
| view_container.add_child2(key, view_holder_token.value, host_import_token)?; |
| import_node.add_child(&host_node); |
| Ok(host_node) |
| } |
| |
| fn setup_text_mod_receiver(app: &App) -> Result<TextInputModProxy, Error> { |
| let text_input_mod = app.connect_to_service(TextInputModMarker)?; |
| |
| let (text_input_receiver, text_input_receiver_request) = |
| create_endpoints::<TextInputModReceiverMarker>()?; |
| |
| fasync::spawn( |
| text_input_receiver_request |
| .into_stream()? |
| .map_ok(move |request| match request { |
| TextInputModReceiverRequest::UserEnteredText { text, responder } => { |
| APP.lock() |
| .handle_suggestion(Some(&text)) |
| .unwrap_or_else(|e| eprintln!("handle_suggestion error: {:?}", e)); |
| responder |
| .send() |
| .unwrap_or_else(|e| eprintln!("UserEnteredText send failed: {:?}", e)); |
| } |
| TextInputModReceiverRequest::UserCanceled { responder } => { |
| APP.lock() |
| .handle_suggestion(None) |
| .unwrap_or_else(|e| eprintln!("handle_suggestion error: {:?}", e)); |
| responder |
| .send() |
| .unwrap_or_else(|e| eprintln!("UserCanceled send failed: {:?}", e)); |
| } |
| }) |
| .try_collect::<()>() |
| .unwrap_or_else(|e| eprintln!("text input receiver error: {:?}", e)), |
| ); |
| |
| let f = text_input_mod.listen_for_text_input(text_input_receiver); |
| fasync::spawn(f.unwrap_or_else(|e| eprintln!("listen_for_text_input error: {:?}", e))); |
| |
| Ok(text_input_mod) |
| } |
| |
| pub fn focus( |
| &mut self, |
| _view_container: &fidl_fuchsia_ui_viewsv1::ViewContainerProxy, |
| ) -> Result<(), Error> { |
| // TODO: add correct scenic focusing call here |
| println!("Want to focus {}", self.key); |
| Ok(()) |
| } |
| |
| pub fn remove( |
| &mut self, |
| view_container: &fidl_fuchsia_ui_viewsv1::ViewContainerProxy, |
| ) -> Result<(), Error> { |
| view_container.remove_child(self.key, None)?; |
| Ok(()) |
| } |
| |
| pub fn new( |
| key: u32, |
| session: &SessionPtr, |
| view_container: &fidl_fuchsia_ui_viewsv1::ViewContainerProxy, |
| import_node: &ImportNode, |
| ) -> Result<AskBox, Error> { |
| let app = Launcher::new()?.launch( |
| "fuchsia-pkg://fuchsia.com/text_input_mod#meta/text_input_mod.cmx".to_string(), |
| None, |
| )?; |
| |
| let host_node = Self::setup_view(&app, key, session, view_container, import_node)?; |
| let text_input_mod = Self::setup_text_mod_receiver(&app)?; |
| |
| Ok(AskBox { _app: app, key, host_node, text_input_mod }) |
| } |
| |
| pub fn layout( |
| &self, |
| view_container: &fidl_fuchsia_ui_viewsv1::ViewContainerProxy, |
| width: f32, |
| height: f32, |
| ) -> Result<(), Error> { |
| let x_inset = width * 0.1; |
| let y_inset = height * 0.4; |
| let mut view_properties = ViewProperties { |
| custom_focus_behavior: Some(Box::new(CustomFocusBehavior { allow_focus: true })), |
| view_layout: Some(Box::new(ViewLayout { |
| inset: InsetF { bottom: 0.0, left: 0.0, right: 0.0, top: 0.0 }, |
| size: SizeF { width: width - 2.0 * x_inset, height: height - 2.0 * y_inset }, |
| })), |
| }; |
| view_container.set_child_properties(self.key, Some(OutOfLine(&mut view_properties)))?; |
| self.host_node.set_translation(x_inset, y_inset, 10.0); |
| |
| Ok(()) |
| } |
| } |