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}