nvdialog_rs/input_box.rs
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2022-2025 Aggelos Tselios
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25use std::ffi::c_void;
26
27use crate::{cstr, string::DynamicString, Object};
28use nvdialog_sys::ffi::*;
29
30/// A struct representing an input box.
31///
32/// Input boxes are similar to [`DialogBox`](crate::DialogBox) ones but instead of just showing text, they also allow the user to
33/// provide some text input. The input field is always single-line. In addition, the [`InputBox`] can display some optional text
34/// to provide more information to the user (Like "Enter your name here").
35///
36/// # Examples
37///
38/// Showing a simple input box, then retrieving the input:
39///
40/// ```
41/// use std::process::abort;
42/// use nvdialog_rs::InputBox;
43///
44/// nvdialog_rs::init().unwrap_or_else(|e| {
45/// eprintln!("Failed to initialize NvDialog: {}", e.to_string());
46/// abort();
47/// });
48/// let mut input_box = InputBox::new(
49/// "Input Box",
50/// "Please enter some text here. The text will be printed to stdout.",
51/// );
52/// input_box.display();
53/// let input = input_box.get_input();
54/// if let Some(string) = input {
55/// println!("You entered the following text: \"{}\"", string);
56/// } else {
57/// eprintln!("You didn't enter anything!");
58/// }
59/// ```
60///
61/// # Safety
62/// The returned string's contents, as described in the NvDialog documentation, is heap-allocated, and therefore it's safe to modify this
63/// string through methods inside the struct. However, **any modifications are applied to the original string DIRECTLY**, meaning that if
64/// you wish to preserve the original string but still modify it somewhere, you should duplicate it instead.
65/// # FFI
66/// Corresponds to `NvdInputBox`.
67pub struct InputBox {
68 raw: *mut NvdInputBox,
69 user_input: Option<DynamicString>,
70}
71
72impl InputBox {
73 #[inline]
74 pub fn new<S: AsRef<str>>(title: S, prompt: S) -> Self {
75 let title = cstr!(title.as_ref());
76 let prompt = cstr!(prompt.as_ref());
77
78 Self {
79 raw: unsafe { nvd_input_box_new(title.as_ptr(), prompt.as_ptr()) },
80 user_input: None,
81 }
82 }
83
84 #[inline]
85 pub fn display(&mut self) {
86 unsafe {
87 nvd_show_input_box(self.raw);
88 let str = DynamicString::from(nvd_input_box_get_string(self.raw));
89 self.user_input = Some(str);
90 }
91 }
92
93 #[inline]
94 pub fn get_input(&mut self) -> Option<DynamicString> {
95 self.user_input.clone()
96 }
97}
98
99impl Object for InputBox {
100 type NativeType = NvdInputBox;
101 type ReturnValue = ();
102
103 fn get_raw(&self) -> *mut Self::NativeType {
104 unimplemented!("NvdInputBox does not have an API to get the raw object yet.");
105 }
106
107 fn show(&self) -> Self::ReturnValue {
108 unimplemented!("Due to trait limitations, use InputBox::display() instead. Object::show() requires that the internal data is not mutated.")
109 }
110
111 fn free(&mut self) {
112 unsafe { nvd_free_object(self.raw as *mut c_void) }
113 }
114}
115
116impl Drop for InputBox {
117 fn drop(&mut self) {
118 self.free();
119 }
120}