summaryrefslogtreecommitdiff
path: root/src/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets')
-rw-r--r--src/widgets/log.rs75
-rw-r--r--src/widgets/menu.rs80
-rw-r--r--src/widgets/prompt.rs68
3 files changed, 223 insertions, 0 deletions
diff --git a/src/widgets/log.rs b/src/widgets/log.rs
new file mode 100644
index 0000000..8bd240a
--- /dev/null
+++ b/src/widgets/log.rs
@@ -0,0 +1,75 @@
+use std::ptr;
+
+use crate::bindings;
+
+pub struct Log {
+ ptr: *mut bindings::Logwidget,
+}
+
+pub struct LogBuilder<'a> {
+ lefttop: (u32, u32),
+ size: (u32, u32),
+ title: Option<&'a str>,
+ timestamps: bool,
+}
+
+impl<'a> LogBuilder<'a> {
+ pub fn add_title<'s: 'a>(&'a mut self, title: &'s str)
+ -> &'a mut LogBuilder<'a> {
+ self.title = Some(title);
+ self
+ }
+
+ pub fn set_timestamps(&'a mut self, timestamps: bool)
+ -> &'a mut LogBuilder<'a> {
+ self.timestamps = timestamps;
+ self
+ }
+
+ pub fn create(&self) -> Log {
+ Log {
+ ptr: unsafe {
+ bindings::lgw_make(
+ self.lefttop.0 as i32, self.lefttop.1 as i32,
+ self.size.0 as i32, self.size.1 as i32,
+ match self.title {
+ None => ptr::null(),
+ Some(s) => s.as_ptr() as *const i8,
+ },
+ self.timestamps)
+ }
+ }
+ }
+}
+
+impl Log {
+ pub fn new<'a>(lefttop: (u32, u32), size: (u32, u32)) -> LogBuilder<'a> {
+ LogBuilder {
+ lefttop, size,
+ title: None,
+ timestamps: false,
+ }
+ }
+
+ pub fn redraw(&self) {
+ unsafe { bindings::lgw_redraw(self.ptr); }
+ }
+
+ pub fn add(&mut self, line: &str) {
+ unsafe { bindings::lgw_add(self.ptr, line.as_ptr() as *const i8); }
+ }
+
+ pub fn clear(&mut self) {
+ unsafe { bindings::lgw_clear(self.ptr); }
+ }
+
+ pub fn change_title(&mut self, title: &str) {
+ unsafe { bindings::lgw_changetitle(self.ptr, title.as_ptr() as *const i8); }
+ }
+}
+
+impl Drop for Log {
+ fn drop(&mut self) {
+ unsafe { bindings::lgw_destroy(self.ptr); }
+ }
+}
diff --git a/src/widgets/menu.rs b/src/widgets/menu.rs
new file mode 100644
index 0000000..fe899e3
--- /dev/null
+++ b/src/widgets/menu.rs
@@ -0,0 +1,80 @@
+use std::ffi::c_void;
+
+use crate::bindings;
+use crate::util;
+
+pub struct Menu {
+ ptr: *mut bindings::Menuwidget,
+ data: *mut bindings::Menudata,
+}
+
+pub struct Data {
+ items: Vec<Item>,
+}
+
+pub struct Item {
+ text: String,
+ hotkey: i32,
+ func: Option<unsafe extern "C" fn(index: i32)>,
+}
+
+pub enum KeyResult {
+ Handled, Ignored, Quit, Called,
+}
+
+impl Menu {
+ pub fn new(lefttop: (u32, u32), data: Data) -> Menu {
+ unsafe {
+ let mdata = util::malloc::<bindings::Menudata>(1);
+ let mitems = util::malloc::<bindings::Menuitem>(data.items.len());
+
+ (*mdata).nitems = data.items.len() as i32;
+ (*mdata).items = mitems;
+
+ for i in 0..data.items.len() {
+ (*mitems.add(i)).text = util::strdup(&data.items[i].text);
+ (*mitems.add(i)).hotkey = data.items[i].hotkey;
+ (*mitems.add(i)).func = data.items[i].func;
+ }
+
+ Menu {
+ ptr: bindings::menu_make(
+ lefttop.0 as i32, lefttop.1 as i32,
+ mdata),
+ data: mdata,
+ }
+ }
+ }
+
+ pub fn redraw(&self) {
+ unsafe { bindings::menu_redraw(self.ptr); }
+ }
+
+ pub fn handle_key(&mut self, key: i32) -> KeyResult {
+ match unsafe { bindings::menu_handlekey(self.ptr, key) } {
+ bindings::Menukey_MENUKEY_HANDLED => KeyResult::Handled,
+ bindings::Menukey_MENUKEY_IGNORED => KeyResult::Ignored,
+ bindings::Menukey_MENUKEY_QUIT => KeyResult::Quit,
+ bindings::Menukey_MENUKEY_CALLED => KeyResult::Called,
+ _ => panic!("Invalid Menukey received from termio"),
+ }
+ }
+}
+
+impl Drop for Menu {
+ fn drop(&mut self) {
+ unsafe {
+ bindings::menu_destroy(self.ptr);
+
+ let nitems = (*self.data).nitems as usize;
+ let mitems = (*self.data).items;
+
+ for i in 0..nitems {
+ libc::free((*mitems.add(i)).text as *mut c_void);
+ }
+
+ libc::free(mitems as *mut c_void);
+ libc::free(self.data as *mut c_void);
+ }
+ }
+}
diff --git a/src/widgets/prompt.rs b/src/widgets/prompt.rs
new file mode 100644
index 0000000..0690840
--- /dev/null
+++ b/src/widgets/prompt.rs
@@ -0,0 +1,68 @@
+use std::ptr;
+
+use crate::bindings;
+use crate::util;
+
+pub struct Prompt {
+ ptr: *mut bindings::Promptwidget,
+}
+
+pub struct PromptBuilder<'a> {
+ lefttop: (u32, u32),
+ width: u32,
+ title: Option<&'a str>,
+}
+
+impl<'a> PromptBuilder<'a> {
+ pub fn add_title<'s: 'a>(&'a mut self, title: &'s str)
+ -> &'a mut PromptBuilder<'a> {
+ self.title = Some(title);
+ self
+ }
+
+ pub fn create(&self) -> Prompt {
+ Prompt {
+ ptr: unsafe {
+ bindings::prw_make(
+ self.lefttop.0 as i32, self.lefttop.1 as i32,
+ self.width as i32,
+ match self.title {
+ None => ptr::null(),
+ Some(s) => s.as_ptr() as *const i8,
+ })
+ }
+ }
+ }
+}
+
+impl Prompt {
+ pub fn new<'a>(lefttop: (u32, u32), width: u32) -> PromptBuilder<'a> {
+ PromptBuilder {
+ lefttop, width,
+ title: None,
+ }
+ }
+
+ pub fn redraw(&self) {
+ unsafe { bindings::prw_redraw(self.ptr); }
+ }
+
+ pub fn handle_key(&mut self, key: i32) -> Option<String> {
+ let ptr = unsafe { bindings::prw_handlekey(self.ptr, key) };
+ if ptr.is_null() {
+ None
+ } else {
+ unsafe { Some(util::string_from_utf8_charp(ptr)) }
+ }
+ }
+
+ pub fn change_title(&mut self, title: &str) {
+ unsafe { bindings::prw_changetitle(self.ptr, title.as_ptr() as *const i8); }
+ }
+}
+
+impl Drop for Prompt {
+ fn drop(&mut self) {
+ unsafe { bindings::prw_destroy(self.ptr); }
+ }
+}