fltk/macros/
browser.rs

1#[doc(hidden)]
2#[macro_export]
3/// Implements BrowserExt
4macro_rules! impl_browser_ext {
5    ($name:tt, $flname:tt) => {
6        paste::paste! {
7            unsafe impl BrowserExt for $name {
8                fn remove(&mut self, line: i32) {
9                    unsafe {
10                        if line > 0 && line <= self.size() + 1 {
11                            [<$flname _remove>](self.inner.widget() as _, line as i32)
12                        }
13                    }
14                }
15
16                fn add(&mut self, item: &str) {
17                    let item = CString::safe_new(item);
18                    unsafe { [<$flname _add>](self.inner.widget() as _, item.as_ptr()) }
19                }
20
21                fn add_with_data<T: Clone + 'static>(&mut self, item: &str, data: T) {
22                    self.add(item);
23                    self.set_data(self.size(), data);
24                }
25
26                fn insert(&mut self, line: i32, item: &str) {
27                    let item = CString::safe_new(item);
28                    unsafe { [<$flname _insert>](self.inner.widget() as _, line as i32, item.as_ptr()) }
29                }
30
31                fn insert_with_data<T: Clone + 'static>(&mut self, line: i32, item: &str, data: T) {
32                    self.insert(line, item);
33                    self.set_data(line, data);
34                }
35
36                fn move_item(&mut self, to: i32, from: i32) {
37                    if to > 0 && to <= self.size() + 1 && from > 0 && from <= self.size() + 1 {
38                        unsafe { [<$flname _move>](self.inner.widget() as _, to as i32, from as i32) }
39                    }
40                }
41
42                fn swap(&mut self, a: i32, b: i32) {
43                    if a > 0 && a <= self.size() + 1 && b > 0 && b <= self.size() + 1 {
44                        unsafe { [<$flname _swap>](self.inner.widget() as _, a as i32, b as i32) }
45                    }
46                }
47
48                fn clear(&mut self) {
49                    unsafe {
50                        [<$flname _clear>](self.inner.widget() as _)
51                    }
52                }
53
54                fn size(&self) -> i32 {
55                    unsafe {
56                        [<$flname _size>](self.inner.widget() as _) as i32
57                    }
58                }
59
60                fn select(&mut self, line: i32) {
61                    if line > 0 && line <= self.size() + 1 {
62                        unsafe {
63                            [<$flname _select>](self.inner.widget() as _, line as i32);
64                        }
65                    }
66                }
67
68                fn deselect(&mut self, line: i32) {
69                    if line > 0 && line <= self.size() + 1 {
70                        unsafe {
71                            [<$flname _select_ext>](self.inner.widget() as _, line as i32, 0);
72                        }
73                    }
74                }
75
76                fn selected(&self, line: i32) -> bool {
77                    if line > 0 && line <= self.size() + 1 {
78                        unsafe {
79                            [<$flname _selected>](self.inner.widget() as _, line as i32) != 0
80                        }
81                    } else {
82                        false
83                    }
84                }
85
86                fn text(&self, line: i32) -> Option<String> {
87                    if line > 0 && line <= self.size() + 1 {
88                        unsafe {
89                            let text = [<$flname _text>](self.inner.widget() as _, line as i32);
90                            if text.is_null() {
91                                None
92                            } else {
93                                Some(
94                                    CStr::from_ptr(text as *mut raw::c_char)
95                                        .to_string_lossy()
96                                        .to_string(),
97                                )
98                            }
99                        }
100                    } else {
101                        None
102                    }
103                }
104
105                fn selected_text(&self) -> Option<String> {
106                    self.text(self.value())
107                }
108
109                fn set_text(&mut self, line: i32, txt: &str) {
110                    if line > 0 && line <= self.size() + 1 {
111                        let txt = CString::safe_new(txt);
112                        unsafe { [<$flname _set_text>](self.inner.widget() as _, line as i32, txt.as_ptr()) }
113                    }
114                }
115
116                fn load<P: AsRef<std::path::Path>>(&mut self, path: P) -> Result<(), FltkError> {
117                    if !$crate::utils::images_registered() {
118                        $crate::utils::register_images();
119                    }
120                    if !path.as_ref().exists() {
121                        return Err(FltkError::Internal(FltkErrorKind::ResourceNotFound));
122                    }
123                    let path = path
124                        .as_ref()
125                        .to_str()
126                        .ok_or(FltkError::Unknown(String::from(
127                            "Failed to convert path to string",
128                        )))?;
129                    let path = CString::new(path)?;
130                    unsafe {
131                        [<$flname _load_file>](self.inner.widget() as _, path.as_ptr());
132                        Ok(())
133                    }
134                }
135
136                fn text_size(&self) -> i32 {
137                    unsafe { [<$flname _text_size>](self.inner.widget() as _) as i32 }
138                }
139
140                fn set_text_size(&mut self, c: i32) {
141                    unsafe {
142                        [<$flname _set_text_size>](self.inner.widget() as _, c as i32)
143                    }
144                }
145
146                fn set_icon<Img: ImageExt>(&mut self, line: i32, image: Option<Img>) {
147                    if line > 0 && line <= self.size() + 1 {
148                        if let Some(image) = image {
149                            assert!(!image.was_deleted());
150                            unsafe {
151                                [<$flname _set_icon>](
152                                    self.inner.widget() as _,
153                                    line as i32,
154                                    image.as_image_ptr() as *mut _,
155                                )
156                            }
157                        } else {
158                            unsafe {
159                                [<$flname _set_icon>](
160                                    self.inner.widget() as _,
161                                    line as i32,
162                                    std::ptr::null_mut() as *mut raw::c_void,
163                                )
164                            }
165                        }
166                    }
167                }
168
169                fn icon(&self, line: i32) -> Option<Box<dyn ImageExt>> {
170                    unsafe {
171                        if line > 0 && line <= self.size() + 1 {
172                            let image_ptr = [<$flname _icon>](self.inner.widget() as _, line as i32);
173                            if image_ptr.is_null() {
174                                None
175                            } else {
176                                let img =
177                                $crate::image::Image::from_image_ptr(image_ptr as *mut fltk_sys::image::Fl_Image);
178                                Some(Box::new(img))
179                            }
180                        } else {
181                            None
182                        }
183                    }
184                }
185
186                fn remove_icon(&mut self, line: i32) {
187                    unsafe {
188                        if line > 0 && line <= self.size() + 1 {
189                            [<$flname _remove_icon>](self.inner.widget() as _, line as i32)
190                        }
191                    }
192                }
193
194                fn top_line(&mut self, line: i32) {
195                    if line > 0 && line <= self.size() + 1 {
196                        unsafe { [<$flname _topline>](self.inner.widget() as _, line as i32) }
197                    }
198                }
199
200                fn bottom_line(&mut self, line: i32) {
201                    if line > 0 && line <= self.size() + 1 {
202                        unsafe { [<$flname _bottomline>](self.inner.widget() as _, line as i32) }
203                    }
204                }
205
206                fn middle_line(&mut self, line: i32) {
207                    if line > 0 && line <= self.size() + 1 {
208                        unsafe { [<$flname _middleline>](self.inner.widget() as _, line as i32) }
209                    }
210                }
211
212                fn format_char(&self) -> char {
213                    unsafe { [<$flname _format_char>](self.inner.widget() as _) as u8 as char }
214                }
215
216                fn set_format_char(&mut self, c: char) {
217                    debug_assert!(c != 0 as char);
218                    let c = if c as i32 > 128 { 128 as char } else { c };
219                    unsafe { [<$flname _set_format_char>](self.inner.widget() as _, c as raw::c_char) }
220                }
221
222                fn column_char(&self) -> char {
223                    unsafe { [<$flname _column_char>](self.inner.widget() as _) as u8 as char }
224                }
225
226                fn set_column_char(&mut self, c: char) {
227                    debug_assert!(c != 0 as char);
228                    let c = if c as i32 > 128 { 128 as char } else { c };
229                    unsafe { [<$flname _set_column_char>](self.inner.widget() as _, c as raw::c_char) }
230                }
231
232                fn column_widths(&self) -> Vec<i32> {
233                    unsafe {
234                        let widths = [<$flname _column_widths>](self.inner.widget() as _);
235                        // Should never throw
236                        assert!(!widths.is_null());
237                        let mut v: Vec<i32> = vec![];
238                        let mut i = 0;
239                        while (*widths.offset(i) != 0) {
240                            v.push(*widths.offset(i));
241                            i += 1;
242                        }
243                        v
244                    }
245                }
246
247                fn set_column_widths(&mut self, arr: &[i32]) {
248                    debug_assert!(!arr.contains(&0), "FLTK uses 0 as a sentinel value for the array/slice. To hide a column, use -1!");
249                    unsafe {
250                        let old = [<$flname _column_widths>](self.inner.widget() as _);
251                        let mut v = arr.to_vec();
252                        v.push(0);
253                        let v = v.into_boxed_slice();
254                        [<$flname _set_column_widths>](self.inner.widget() as _, Box::into_raw(v) as _);
255                        if !old.is_null() && *old.offset(0) != 0 {
256                            let _ = Box::from_raw(old as *mut i32);
257                        }
258                    }
259                }
260
261                fn displayed(&self, line: i32) -> bool {
262                    if line > 0 && line <= self.size() + 1 {
263                    unsafe { [<$flname _displayed>](self.inner.widget() as _, line as i32) != 0 }
264                    } else {
265                        false
266                    }
267                }
268
269                fn make_visible(&mut self, line: i32) {
270                    if line > 0 && line <= self.size() + 1 {
271                        unsafe { [<$flname _make_visible>](self.inner.widget() as _, line as i32) }
272                    }
273                }
274
275                fn vposition(&self) -> i32 {
276                    unsafe { [<$flname _position>](self.inner.widget() as _) as i32 }
277                }
278
279                fn set_vposition(&mut self, pos: i32) {
280                    unsafe { [<$flname _set_position>](self.inner.widget() as _, pos as i32) }
281                }
282
283                fn hposition(&self) -> i32 {
284                    unsafe { [<$flname _hposition>](self.inner.widget() as _) as i32 }
285                }
286
287                fn set_hposition(&mut self, pos: i32) {
288                    unsafe { [<$flname _set_hposition>](self.inner.widget() as _, pos as i32) }
289                }
290
291                fn has_scrollbar(&self) -> $crate::browser::BrowserScrollbar {
292                    unsafe { std::mem::transmute([<$flname _has_scrollbar>](self.inner.widget() as _)) }
293                }
294
295                fn set_has_scrollbar(&mut self, mode: $crate::browser::BrowserScrollbar) {
296                    unsafe {
297                        [<$flname _set_has_scrollbar>](self.inner.widget() as _, mode as raw::c_uchar)
298                    }
299                }
300
301                fn scrollbar_size(&self) -> i32 {
302                    unsafe { [<$flname _scrollbar_size>](self.inner.widget() as _) as i32 }
303                }
304
305                fn set_scrollbar_size(&mut self, new_size: i32) {
306                    unsafe { [<$flname _set_scrollbar_size>](self.inner.widget() as _, new_size as i32) }
307                }
308
309                fn sort(&mut self) {
310                    unsafe { [<$flname _sort>](self.inner.widget() as _) }
311                }
312
313                fn scrollbar(&self) -> $crate::valuator::Scrollbar {
314                    unsafe {
315                        let ptr = [<$flname _scrollbar>](self.inner.widget() as _);
316                        assert!(!ptr.is_null());
317                        $crate::valuator::Scrollbar::from_widget_ptr(
318                            ptr as *mut fltk_sys::widget::Fl_Widget,
319                        )
320                    }
321                }
322
323                fn hscrollbar(&self) -> $crate::valuator::Scrollbar {
324                    unsafe {
325                        let ptr = [<$flname _hscrollbar>](self.inner.widget() as _);
326                        assert!(!ptr.is_null());
327                        $crate::valuator::Scrollbar::from_widget_ptr(
328                            ptr as *mut fltk_sys::widget::Fl_Widget,
329                        )
330                    }
331                }
332
333                fn value(&self) -> i32 {
334                    unsafe { [<$flname _value>](self.inner.widget() as _) as i32 }
335                }
336
337                fn set_data<T: Clone + 'static>(&mut self, line: i32, data: T) {
338                    if line > 0 && line <= self.size() + 1 {
339                    unsafe {
340                            [<$flname _set_data>](self.inner.widget() as _, line, Box::into_raw(Box::from(data)) as _);
341                        }
342                    }
343                }
344
345                unsafe fn data<T: Clone + 'static>(&self, line: i32) -> Option<T> { unsafe {
346                    if line > 0 && line <= self.size() + 1 {
347                        let ptr = [<$flname _data>](self.inner.widget() as _, line);
348                        if ptr.is_null() {
349                            None
350                        } else {
351                            let data = ptr as *const _ as *mut T;
352                            Some((*data).clone())
353                        }
354                    } else {
355                        None
356                    }
357                }}
358
359                fn hide_line(&mut self, line: i32) {
360                    if line > 0 && line <= self.size() + 1 {
361                    unsafe { [<$flname _hide_line>](self.inner.widget() as _, line); }
362                    }
363                }
364
365                fn selected_items(&self) -> Vec<i32> {
366                    let mut temp = vec![];
367                    if self.value() > 0 {
368                        for i in 1..self.size() + 1 {
369                            if self.selected(i) {
370                                temp.push(i);
371                            }
372                        }
373                    }
374                    temp
375                }
376            }
377        }
378    };
379}
380
381pub use impl_browser_ext;