2023-01-16 09:53:52 +00:00
|
|
|
use crate::prelude::*;
|
|
|
|
use anyhow::Result;
|
2025-03-04 17:18:08 +00:00
|
|
|
use ecs::World;
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
use std::any::Any;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::{
|
|
|
|
ops::Deref,
|
|
|
|
sync::{Arc, RwLock},
|
|
|
|
};
|
|
|
|
|
2024-05-18 05:54:06 +00:00
|
|
|
#[derive(Debug)]
|
2023-01-16 09:53:52 +00:00
|
|
|
enum KeyboardMode {
|
|
|
|
LowerCase,
|
|
|
|
UpperCase,
|
|
|
|
Specials,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Keyboard {
|
|
|
|
text_field_gui: Arc<GuiBuilder>,
|
|
|
|
text_field: Arc<TextField>,
|
|
|
|
|
|
|
|
lower_case: Arc<GuiBuilder>,
|
|
|
|
upper_case: Arc<GuiBuilder>,
|
|
|
|
specials: Arc<GuiBuilder>,
|
|
|
|
|
|
|
|
mode: Arc<RwLock<KeyboardMode>>,
|
|
|
|
|
2025-03-04 17:18:08 +00:00
|
|
|
decline_callback: Arc<RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>>,
|
|
|
|
accept_callback:
|
|
|
|
Arc<RwLock<Option<Box<dyn Fn(&mut World, &dyn Any) -> Result<()> + Send + Sync>>>>,
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
elements: HashMap<String, UiElement>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Keyboard {
|
2025-03-05 06:59:38 +00:00
|
|
|
pub fn new(world: &mut World) -> Result<Arc<Self>> {
|
2023-01-16 09:53:52 +00:00
|
|
|
let text_field_gui: Arc<GuiBuilder> =
|
2025-03-05 06:59:38 +00:00
|
|
|
GuiBuilder::from_str(world, include_str!("text_field.xml"))?;
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
let text_field: Arc<TextField> = text_field_gui.element("field")?;
|
|
|
|
|
2025-03-04 13:25:35 +00:00
|
|
|
let decline_callback: Arc<
|
2025-03-04 17:18:08 +00:00
|
|
|
RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>,
|
2025-03-04 13:25:35 +00:00
|
|
|
> = Arc::new(RwLock::new(None));
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
let accept_callback: Arc<
|
2025-03-04 17:18:08 +00:00
|
|
|
RwLock<Option<Box<dyn Fn(&mut World, &dyn Any) -> Result<()> + Send + Sync>>>,
|
2023-01-16 09:53:52 +00:00
|
|
|
> = Arc::new(RwLock::new(None));
|
|
|
|
|
|
|
|
let mode = Arc::new(RwLock::new(KeyboardMode::UpperCase));
|
|
|
|
|
|
|
|
let (lower_case, upper_case, specials) = Self::setup(
|
2025-03-05 06:59:38 +00:00
|
|
|
world,
|
2023-01-16 09:53:52 +00:00
|
|
|
text_field.clone(),
|
|
|
|
&mode,
|
|
|
|
decline_callback.clone(),
|
|
|
|
accept_callback.clone(),
|
|
|
|
)?;
|
|
|
|
|
|
|
|
let mut elements = HashMap::new();
|
|
|
|
|
|
|
|
elements.insert(
|
|
|
|
"text".to_string(),
|
|
|
|
UiElement::TextField(Arc::downgrade(&text_field)),
|
|
|
|
);
|
|
|
|
|
|
|
|
Ok(Arc::new(Keyboard {
|
|
|
|
text_field_gui,
|
|
|
|
text_field,
|
|
|
|
|
|
|
|
lower_case,
|
|
|
|
upper_case,
|
|
|
|
specials,
|
|
|
|
|
|
|
|
mode,
|
|
|
|
|
|
|
|
decline_callback,
|
|
|
|
accept_callback,
|
|
|
|
|
|
|
|
elements,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn setup(
|
2025-03-05 06:59:38 +00:00
|
|
|
world: &mut World,
|
2023-01-16 09:53:52 +00:00
|
|
|
textfield: Arc<TextField>,
|
|
|
|
mode: &Arc<RwLock<KeyboardMode>>,
|
2025-03-04 17:18:08 +00:00
|
|
|
decline_callback: Arc<RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>>,
|
|
|
|
accept_callback: Arc<
|
|
|
|
RwLock<Option<Box<dyn Fn(&mut World, &dyn Any) -> Result<()> + Send + Sync>>>,
|
2025-03-04 13:25:35 +00:00
|
|
|
>,
|
2023-01-16 09:53:52 +00:00
|
|
|
) -> Result<(Arc<GuiBuilder>, Arc<GuiBuilder>, Arc<GuiBuilder>)> {
|
2025-03-05 06:59:38 +00:00
|
|
|
let lower_case = GuiBuilder::from_str(world, include_str!("lower_case.xml"))?;
|
|
|
|
let upper_case = GuiBuilder::from_str(world, include_str!("upper_case.xml"))?;
|
|
|
|
let specials = GuiBuilder::from_str(world, include_str!("specials.xml"))?;
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
// first row
|
|
|
|
Self::set_text_callback(&lower_case, "q", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "w", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "e", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "r", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "t", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "y", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "u", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "i", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "o", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "p", textfield.clone())?;
|
|
|
|
|
|
|
|
// second row
|
|
|
|
Self::set_text_callback(&lower_case, "a", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "s", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "d", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "f", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "g", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "h", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "j", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "k", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "l", textfield.clone())?;
|
|
|
|
|
|
|
|
// third row
|
|
|
|
Self::set_text_callback(&lower_case, "z", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "x", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "c", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "v", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "b", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "n", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&lower_case, "m", textfield.clone())?;
|
|
|
|
|
|
|
|
// first row
|
|
|
|
Self::set_text_callback(&upper_case, "Q", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "W", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "E", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "R", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "T", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "Y", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "U", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "I", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "O", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "P", textfield.clone())?;
|
|
|
|
|
|
|
|
// second row
|
|
|
|
Self::set_text_callback(&upper_case, "A", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "S", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "D", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "F", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "G", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "H", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "J", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "K", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "L", textfield.clone())?;
|
|
|
|
|
|
|
|
// third row
|
|
|
|
Self::set_text_callback(&upper_case, "Z", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "X", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "C", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "V", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "B", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "N", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&upper_case, "M", textfield.clone())?;
|
|
|
|
|
|
|
|
// first row
|
|
|
|
Self::set_text_callback(&specials, "1", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "2", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "3", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "4", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "5", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "6", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "7", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "8", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "9", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "0", textfield.clone())?;
|
|
|
|
|
|
|
|
// second row
|
|
|
|
Self::set_text_callback(&specials, "!", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "^", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "\\", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "*", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "%", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "~", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "/", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "(", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, ")", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "=", textfield.clone())?;
|
|
|
|
|
|
|
|
// third row
|
|
|
|
Self::set_text_callback(&specials, "#", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "+", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "{", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "}", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, ":", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, ";", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "-", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, ",", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, ".", textfield.clone())?;
|
|
|
|
Self::set_text_callback(&specials, "_", textfield.clone())?;
|
|
|
|
|
2025-03-04 17:18:08 +00:00
|
|
|
let back = Box::new(move |world: &mut World| {
|
2023-01-16 09:53:52 +00:00
|
|
|
if let Some(callback) = decline_callback.read().unwrap().as_ref() {
|
2025-03-04 17:18:08 +00:00
|
|
|
(callback)(world)?;
|
2023-01-16 09:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
|
|
|
|
let accept = {
|
|
|
|
let weak_textfield = Arc::downgrade(&textfield);
|
|
|
|
let weak_accept = Arc::downgrade(&accept_callback);
|
|
|
|
|
2025-03-04 17:18:08 +00:00
|
|
|
Box::new(move |world: &mut World| {
|
2023-01-16 09:53:52 +00:00
|
|
|
if let Some(textfield) = weak_textfield.upgrade() {
|
|
|
|
if let Some(accept_callback) = weak_accept.upgrade() {
|
|
|
|
if let Some(text) = textfield.text() {
|
|
|
|
if let Some(callback) = accept_callback.read().unwrap().as_ref() {
|
2025-03-04 17:18:08 +00:00
|
|
|
(callback)(world, &text)?;
|
2023-01-16 09:53:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
|
|
|
let switch_to_upper = {
|
|
|
|
let mode = mode.clone();
|
|
|
|
let weak_lower = Arc::downgrade(&lower_case);
|
|
|
|
let weak_upper = Arc::downgrade(&upper_case);
|
|
|
|
|
2025-03-04 17:18:08 +00:00
|
|
|
Box::new(move |world: &mut World| {
|
2023-01-16 09:53:52 +00:00
|
|
|
if let Some(lower) = weak_lower.upgrade() {
|
|
|
|
if let Some(upper) = weak_upper.upgrade() {
|
|
|
|
let mut mode = mode.write().unwrap();
|
|
|
|
|
|
|
|
if let KeyboardMode::LowerCase = mode.deref() {
|
|
|
|
*mode = KeyboardMode::UpperCase;
|
2025-03-04 17:18:08 +00:00
|
|
|
|
2025-03-05 06:59:38 +00:00
|
|
|
lower.disable(world)?;
|
|
|
|
upper.enable(world)?;
|
2023-01-16 09:53:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
|
|
|
let switch_to_special = {
|
|
|
|
let mode = mode.clone();
|
|
|
|
let weak_upper = Arc::downgrade(&upper_case);
|
|
|
|
let weak_specials = Arc::downgrade(&specials);
|
|
|
|
|
2025-03-04 17:18:08 +00:00
|
|
|
Box::new(move |world: &mut World| {
|
2023-01-16 09:53:52 +00:00
|
|
|
if let Some(specials) = weak_specials.upgrade() {
|
|
|
|
if let Some(upper) = weak_upper.upgrade() {
|
|
|
|
let mut mode = mode.write().unwrap();
|
|
|
|
|
|
|
|
if let KeyboardMode::UpperCase = mode.deref() {
|
|
|
|
*mode = KeyboardMode::Specials;
|
2025-03-04 17:18:08 +00:00
|
|
|
|
2025-03-05 06:59:38 +00:00
|
|
|
upper.disable(world)?;
|
|
|
|
specials.enable(world)?;
|
2023-01-16 09:53:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
|
|
|
let switch_to_lower = {
|
|
|
|
let mode = mode.clone();
|
|
|
|
let weak_lower = Arc::downgrade(&lower_case);
|
|
|
|
let weak_specials = Arc::downgrade(&specials);
|
|
|
|
|
2025-03-04 17:18:08 +00:00
|
|
|
Box::new(move |world: &mut World| {
|
2023-01-16 09:53:52 +00:00
|
|
|
if let Some(lower) = weak_lower.upgrade() {
|
|
|
|
if let Some(specials) = weak_specials.upgrade() {
|
|
|
|
let mut mode = mode.write().unwrap();
|
|
|
|
|
|
|
|
if let KeyboardMode::Specials = mode.deref() {
|
|
|
|
*mode = KeyboardMode::LowerCase;
|
2025-03-04 17:18:08 +00:00
|
|
|
|
2025-03-05 06:59:38 +00:00
|
|
|
specials.disable(world)?;
|
|
|
|
lower.enable(world)?;
|
2023-01-16 09:53:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
|
|
|
let space_bar = {
|
|
|
|
let weak_textfield = Arc::downgrade(&textfield);
|
|
|
|
|
2025-03-04 17:18:08 +00:00
|
|
|
Box::new(move |world: &mut World| {
|
2023-01-16 09:53:52 +00:00
|
|
|
if let Some(text_field) = weak_textfield.upgrade() {
|
2025-03-04 17:18:08 +00:00
|
|
|
let gui_handler = world.resources.get_mut::<GuiHandler>();
|
2025-03-04 13:25:35 +00:00
|
|
|
text_field.add_letter(gui_handler, ' ')?;
|
2023-01-16 09:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
|
|
|
lower_case.set_click_callbacks(vec![
|
|
|
|
("back", back.clone()),
|
|
|
|
("enter", accept.clone()),
|
|
|
|
("switch", switch_to_upper),
|
|
|
|
("space_bar", space_bar.clone()),
|
|
|
|
])?;
|
|
|
|
specials.set_click_callbacks(vec![
|
|
|
|
("back", back.clone()),
|
|
|
|
("enter", accept.clone()),
|
|
|
|
("switch", switch_to_lower),
|
|
|
|
("space_bar", space_bar.clone()),
|
|
|
|
])?;
|
|
|
|
upper_case.set_click_callbacks(vec![
|
|
|
|
("back", back),
|
|
|
|
("enter", accept),
|
|
|
|
("switch", switch_to_special),
|
|
|
|
("space_bar", space_bar),
|
|
|
|
])?;
|
|
|
|
|
|
|
|
Ok((lower_case, upper_case, specials))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_text_callback(
|
|
|
|
builder: &Arc<GuiBuilder>,
|
|
|
|
letter: &str,
|
|
|
|
textfield: Arc<TextField>,
|
|
|
|
) -> Result<()> {
|
|
|
|
let button_ref: Arc<Button> = builder.element(letter)?;
|
|
|
|
|
|
|
|
let weak_textfield = Arc::downgrade(&textfield);
|
|
|
|
let weak_button = Arc::downgrade(&button_ref);
|
|
|
|
|
2025-03-04 17:18:08 +00:00
|
|
|
button_ref.set_callback(Box::new(move |world: &mut World| {
|
2023-01-16 09:53:52 +00:00
|
|
|
if let Some(textfield) = weak_textfield.upgrade() {
|
|
|
|
if let Some(button) = weak_button.upgrade() {
|
|
|
|
if let Some(text) = button.text()? {
|
2025-03-04 17:18:08 +00:00
|
|
|
let gui_handler = world.resources.get_mut::<GuiHandler>();
|
2025-03-04 13:25:35 +00:00
|
|
|
textfield.add_letter(gui_handler, text.as_bytes()[0] as char)?;
|
2023-01-16 09:53:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}));
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TopGui for Keyboard {
|
2025-03-04 17:18:08 +00:00
|
|
|
fn decline(&self, world: &mut World) -> Result<()> {
|
2023-01-16 09:53:52 +00:00
|
|
|
if let Some(callback) = self.decline_callback.read().unwrap().as_ref() {
|
2025-03-04 17:18:08 +00:00
|
|
|
(callback)(world)?;
|
2023-01-16 09:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2025-03-04 17:18:08 +00:00
|
|
|
fn next_tab(&self, _world: &mut World, _: bool) -> Result<()> {
|
2023-01-16 09:53:52 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2025-03-04 17:18:08 +00:00
|
|
|
fn previous_tab(&self, world: &mut World, second_level: bool) -> Result<()> {
|
2023-01-16 09:53:52 +00:00
|
|
|
// abuse event
|
|
|
|
if !second_level {
|
2025-03-04 17:18:08 +00:00
|
|
|
let gui_handler = world.resources.get_mut::<GuiHandler>();
|
2025-03-04 13:25:35 +00:00
|
|
|
self.text_field.remove_last(gui_handler)?;
|
2023-01-16 09:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Visibility for Keyboard {
|
|
|
|
fn visible(&self) -> bool {
|
|
|
|
let mode = self.mode.read().unwrap();
|
|
|
|
|
|
|
|
match mode.deref() {
|
|
|
|
KeyboardMode::LowerCase => self.lower_case.visible(),
|
|
|
|
KeyboardMode::UpperCase => self.upper_case.visible(),
|
|
|
|
KeyboardMode::Specials => self.specials.visible(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-03-05 06:59:38 +00:00
|
|
|
fn set_visibility(&self, world: &mut World, visibility: bool) -> Result<()> {
|
2023-01-16 09:53:52 +00:00
|
|
|
let mode = self.mode.read().unwrap();
|
|
|
|
|
2024-05-18 05:54:06 +00:00
|
|
|
let gui = match mode.deref() {
|
|
|
|
KeyboardMode::LowerCase => &self.lower_case,
|
|
|
|
KeyboardMode::UpperCase => &self.upper_case,
|
|
|
|
KeyboardMode::Specials => &self.specials,
|
|
|
|
};
|
2023-01-16 09:53:52 +00:00
|
|
|
|
2024-05-18 05:54:06 +00:00
|
|
|
if visibility {
|
2025-03-05 06:59:38 +00:00
|
|
|
gui.enable(world)?;
|
|
|
|
self.text_field_gui.enable(world)?;
|
2024-05-18 05:54:06 +00:00
|
|
|
} else {
|
2025-03-05 06:59:38 +00:00
|
|
|
gui.disable(world)?;
|
|
|
|
self.text_field_gui.disable(world)?;
|
2024-05-18 05:54:06 +00:00
|
|
|
}
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl GuiElementTraits for Keyboard {
|
|
|
|
fn gridable(&self) -> Option<&dyn Gridable> {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visibility(&self) -> Option<&dyn Visibility> {
|
|
|
|
Some(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn downcast<'a>(&'a self) -> Option<GuiElement<'a>> {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TopLevelGui for Keyboard {
|
|
|
|
fn gui_traits(&self) -> &dyn GuiElementTraits {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn top_gui(&self) -> Option<&dyn TopGui> {
|
|
|
|
Some(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn elements(&self) -> Option<&HashMap<String, UiElement>> {
|
|
|
|
Some(&self.elements)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn functionality(&self) -> Option<&dyn Functionality> {
|
|
|
|
Some(self)
|
|
|
|
}
|
|
|
|
|
2025-03-05 06:59:38 +00:00
|
|
|
fn enable(&self, world: &mut World) -> Result<()> {
|
|
|
|
self.set_visibility(world, true)?;
|
|
|
|
self.text_field
|
|
|
|
.focus_input(world.resources.get_mut::<GuiHandler>())?;
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2025-03-05 06:59:38 +00:00
|
|
|
fn disable(&self, world: &mut World) -> Result<()> {
|
|
|
|
self.set_visibility(world, false)?;
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Functionality for Keyboard {
|
|
|
|
fn set_click_callbacks(
|
|
|
|
&self,
|
2025-03-04 17:18:08 +00:00
|
|
|
callbacks: Vec<(&str, Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>)>,
|
2023-01-16 09:53:52 +00:00
|
|
|
) -> Result<()> {
|
2025-03-04 17:18:08 +00:00
|
|
|
if let Some((_, callback)) = callbacks.into_iter().find(|(name, _)| *name == "decline") {
|
|
|
|
*self.decline_callback.write().unwrap() = Some(callback);
|
2023-01-16 09:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2025-03-04 17:18:08 +00:00
|
|
|
fn set_select_callbacks(
|
|
|
|
&self,
|
|
|
|
_: Vec<(
|
|
|
|
&str,
|
|
|
|
Box<dyn Fn(&mut World, bool) -> Result<()> + Send + Sync>,
|
|
|
|
)>,
|
|
|
|
) -> Result<()> {
|
2023-01-16 09:53:52 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_custom_callbacks(
|
|
|
|
&self,
|
|
|
|
_: Vec<(
|
|
|
|
&str,
|
2025-03-04 17:18:08 +00:00
|
|
|
Box<dyn Fn(&mut World, ControllerButton) -> Result<bool> + Send + Sync>,
|
2023-01-16 09:53:52 +00:00
|
|
|
)>,
|
|
|
|
) -> Result<()> {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_vec_callbacks(
|
|
|
|
&self,
|
2025-03-04 17:18:08 +00:00
|
|
|
callbacks: Vec<(
|
|
|
|
&str,
|
|
|
|
Box<dyn Fn(&mut World, &dyn Any) -> Result<()> + Send + Sync>,
|
|
|
|
)>,
|
2023-01-16 09:53:52 +00:00
|
|
|
) -> Result<()> {
|
|
|
|
for (name, callback) in callbacks {
|
|
|
|
if name == "accept" {
|
|
|
|
*self.accept_callback.write().unwrap() = Some(callback);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|