rstk/
listbox.rs

1//! Listbox widget - displays a list of items from which the user can select 
2//! one or more.
3//!
4//! * also see the Tk [manual](https://www.tcl-lang.org/man/tcl8.6/TkCmd/listbox.htm)
5//!
6//! # Events
7//!
8//! Use [bind](widget::TkWidget::bind) to call a function on following event:
9//!
10//! * `<<ListboxSelect>>` - whenever selection is changed
11
12use super::grid;
13use super::pack;
14use super::widget;
15use super::wish;
16
17/// Refers to a listbox widget
18#[derive(Clone, Debug, PartialEq)]
19pub struct TkListbox {
20    pub id: String,
21}
22
23/// Creates an instance of a listbox widget in given parent
24/// populating the listbox with the given set of values.
25pub fn make_listbox(parent: &impl widget::TkWidget, values: &[&str]) -> TkListbox {
26    let id = wish::next_wid(parent.id());
27
28    let msg = format!("listbox {}", id);
29    wish::tell_wish(&msg);
30
31    // - add values to listbox
32    for value in values {
33        let msg = format!("{} insert end {{{}}}", id, value);
34        wish::tell_wish(&msg);
35    }
36    // - select first item at start
37    let msg = format!("{} selection set 0", id);
38    wish::tell_wish(&msg);
39
40    TkListbox { id }
41}
42
43impl widget::TkWidget for TkListbox {
44    /// Returns the widget's id reference - used within tk
45    fn id(&self) -> &str {
46        &self.id
47    }
48}
49
50impl grid::TkGridLayout for TkListbox {}
51impl pack::TkPackLayout for TkListbox {}
52
53impl TkListbox {
54    /// Adds item to end of list.
55    pub fn append(&self, item: &str) {
56        let msg = format!("{} insert end {{{}}}", &self.id, item);
57        wish::tell_wish(&msg);
58    }
59
60    /// Size of border around listbox.
61    pub fn border_width(&self, width: u64) {
62        widget::configure(&self.id, "borderwidth", &width.to_string());
63    }
64
65    /// Delete item at given index.
66    pub fn delete(&self, index: u64) {
67        let msg = format!("{} delete {}", &self.id, index);
68        wish::tell_wish(&msg);
69    }
70
71    /// Specifies the font to use for text.
72    pub fn font(&self, definition: &str) {
73        widget::configure(&self.id, "font", definition);
74    }
75
76    /// Height of listbox, in rows.
77    pub fn height(&self, height: u64) {
78        widget::configure(&self.id, "height", &height.to_string());
79    }
80
81    /// Insert item at given index.
82    pub fn insert_at(&self, index: u64, item: &str) {
83        let msg = format!("{} insert {} {{{}}}", &self.id, index, item);
84        wish::tell_wish(&msg);
85    }
86
87    /// Set configuration option for given item index.
88    pub fn item_configure(&self, index: u64, option: &str, value: &str) {
89        let msg = format!(
90            "{} itemconfigure {} -{} {{{}}}",
91            &self.id, index, option, value
92        );
93        wish::tell_wish(&msg);
94    }
95
96    /// Alignment of text within widget.
97    pub fn justify(&self, value: widget::Justify) {
98        widget::configure(&self.id, "justify", &value.to_string());
99    }
100
101    /// Style of border around listbox.
102    pub fn relief(&self, value: widget::Relief) {
103        widget::configure(&self.id, "relief", &value.to_string());
104    }
105
106    /// Selection mode, one of "single" or "multiple" ("none" is made "single").
107    pub fn selection_mode(&self, value: widget::Selection) {
108        let value = if value == widget::Selection::None {
109            widget::Selection::Single.to_string()
110        } else {
111            value.to_string()
112        };
113        widget::configure(&self.id, "selectmode", &value);
114    }
115
116    /// Returns list of indices for selected items.
117    pub fn selected_items(&self) -> Vec<u64> {
118        let query = format!("puts [{} curselection] ; flush stdout", &self.id);
119        let values = wish::ask_wish(&query);
120
121        let mut result: Vec<u64> = vec![];
122        for value in values.split_whitespace() {
123            if let Ok(value) = value.parse::<u64>() {
124                result.push(value);
125            }
126        }
127
128        result
129    }
130
131    /// Sets the state of the listbox (normal or disabled).
132    pub fn state(&self, value: widget::State) {
133        widget::configure(&self.id, "state", &value.to_string());
134    }
135
136    /// Width of listbox, in characters.
137    pub fn width(&self, width: u64) {
138        widget::configure(&self.id, "width", &width.to_string());
139    }
140}