Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions src/runtime/settings/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ use core::mem;
#[cfg(feature = "derive")]
pub use asr_derive::Gui;

#[cfg(feature = "alloc")]
use alloc::borrow::ToOwned;

use crate::{runtime::sys, watcher::Pair};

use super::map::Map;
Expand Down Expand Up @@ -166,6 +169,26 @@ pub fn add_file_select_mime_filter(key: &str, mime_type: &str) {
}
}

/// Adds a new text input setting widget that the user can modify. The key is
/// used to store the text in the settings [`Map`](super::Map) and needs to be
/// unique across all types of settings. The description is what's shown to the
/// user. The default value is used when the user hasn't set a value yet.
#[inline]
pub fn add_text_input(key: &str, description: &str, default_value: &str) {
// SAFETY: We provide valid pointers and lengths to key, description and
// default_value. They are also guaranteed to be valid UTF-8 strings.
unsafe {
sys::user_settings_add_text_input(
key.as_ptr(),
key.len(),
description.as_ptr(),
description.len(),
default_value.as_ptr(),
default_value.len(),
)
}
}

/// Adds a tooltip to a setting widget based on its key. A tooltip is useful for
/// explaining the purpose of a setting to the user.
#[inline]
Expand Down Expand Up @@ -357,3 +380,65 @@ impl Widget for FileSelect {
}
}
}

/// A text input widget.
///
/// This is useful for settings where the user needs to enter arbitrary text,
/// such as a scene or level name to split on.
///
/// # Example
///
/// ```ignore
/// #[derive(Gui)]
/// struct Settings {
/// /// Screen Name
/// ///
/// /// Split when entering a scene with this name.
/// #[default = "prologue"]
/// level_name: TextInput,
/// }
///
/// // In your auto splitter:
/// if current_scene == settings.level_name.value {
/// timer::split();
/// }
/// ```
#[derive(Clone, PartialEq, Eq)]
#[cfg(feature = "alloc")]
pub struct TextInput {
/// The text entered by the user, or the default if they haven't changed it.
pub value: alloc::string::String,
}

/// The arguments that are needed to register a text input widget. This is an
/// internal type that you don't need to worry about.
#[cfg(feature = "alloc")]
#[doc(hidden)]
#[derive(Default)]
#[non_exhaustive]
pub struct TextInputArgs {
/// The default value of the setting, in case the user didn't set it yet.
pub default: &'static str,
}

#[cfg(feature = "alloc")]
impl Widget for TextInput {
type Args = TextInputArgs;

fn register(key: &str, description: &str, args: Self::Args) -> Self {
add_text_input(key, description, args.default);
let mut this = TextInput {
value: alloc::string::String::new(),
};
this.update_from(&Map::load(), key, args);
this
}

fn update_from(&mut self, settings_map: &Map, key: &str, args: Self::Args) {
if let Some(value) = settings_map.get(key) {
value.get_string_into(&mut self.value);
} else {
args.default.clone_into(&mut self.value);
}
}
}
13 changes: 13 additions & 0 deletions src/runtime/sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,19 @@ extern "C" {
mime_type_ptr: *const u8,
mime_type_len: usize,
);
/// Adds a new text input setting that the user can modify. The key is used
/// to store the text in the settings map and needs to be unique across all
/// types of settings. The description is what's shown to the user. The
/// pointers need to point to valid UTF-8 encoded text with the respective
/// given length.
pub fn user_settings_add_text_input(
key_ptr: *const u8,
key_len: usize,
description_ptr: *const u8,
description_len: usize,
default_value_ptr: *const u8,
default_value_len: usize,
);
/// Adds a tooltip to a setting based on its key. A tooltip is useful for
/// explaining the purpose of a setting to the user. The pointers need to
/// point to valid UTF-8 encoded text with the respective given length.
Expand Down