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 !path.as_ref().exists() {
118                        return Err(FltkError::Internal(FltkErrorKind::ResourceNotFound));
119                    }
120                    let path = path
121                        .as_ref()
122                        .to_str()
123                        .ok_or(FltkError::Unknown(String::from(
124                            "Failed to convert path to string",
125                        )))?;
126                    let path = CString::new(path)?;
127                    unsafe {
128                        [<$flname _load_file>](self.inner.widget() as _, path.as_ptr());
129                        Ok(())
130                    }
131                }
132
133                fn text_size(&self) -> i32 {
134                    unsafe { [<$flname _text_size>](self.inner.widget() as _) as i32 }
135                }
136
137                fn set_text_size(&mut self, c: i32) {
138                    unsafe {
139                        [<$flname _set_text_size>](self.inner.widget() as _, c as i32)
140                    }
141                }
142
143                fn set_icon<Img: ImageExt>(&mut self, line: i32, image: Option<Img>) {
144                    if line > 0 && line <= self.size() + 1 {
145                        if let Some(image) = image {
146                            assert!(!image.was_deleted());
147                            unsafe {
148                                [<$flname _set_icon>](
149                                    self.inner.widget() as _,
150                                    line as i32,
151                                    image.as_image_ptr() as *mut _,
152                                )
153                            }
154                        } else {
155                            unsafe {
156                                [<$flname _set_icon>](
157                                    self.inner.widget() as _,
158                                    line as i32,
159                                    std::ptr::null_mut() as *mut raw::c_void,
160                                )
161                            }
162                        }
163                    }
164                }
165
166                fn icon(&self, line: i32) -> Option<Box<dyn ImageExt>> {
167                    unsafe {
168                        if line > 0 && line <= self.size() + 1 {
169                            let image_ptr = [<$flname _icon>](self.inner.widget() as _, line as i32);
170                            if image_ptr.is_null() {
171                                None
172                            } else {
173                                let img =
174                                $crate::image::Image::from_image_ptr(image_ptr as *mut fltk_sys::image::Fl_Image);
175                                Some(Box::new(img))
176                            }
177                        } else {
178                            None
179                        }
180                    }
181                }
182
183                fn remove_icon(&mut self, line: i32) {
184                    unsafe {
185                        if line > 0 && line <= self.size() + 1 {
186                            [<$flname _remove_icon>](self.inner.widget() as _, line as i32)
187                        }
188                    }
189                }
190
191                fn top_line(&mut self, line: i32) {
192                    if line > 0 && line <= self.size() + 1 {
193                        unsafe { [<$flname _topline>](self.inner.widget() as _, line as i32) }
194                    }
195                }
196
197                fn bottom_line(&mut self, line: i32) {
198                    if line > 0 && line <= self.size() + 1 {
199                        unsafe { [<$flname _bottomline>](self.inner.widget() as _, line as i32) }
200                    }
201                }
202
203                fn middle_line(&mut self, line: i32) {
204                    if line > 0 && line <= self.size() + 1 {
205                        unsafe { [<$flname _middleline>](self.inner.widget() as _, line as i32) }
206                    }
207                }
208
209                fn format_char(&self) -> char {
210                    unsafe { [<$flname _format_char>](self.inner.widget() as _) as u8 as char }
211                }
212
213                fn set_format_char(&mut self, c: char) {
214                    debug_assert!(c != 0 as char);
215                    let c = if c as i32 > 128 { 128 as char } else { c };
216                    unsafe { [<$flname _set_format_char>](self.inner.widget() as _, c as raw::c_char) }
217                }
218
219                fn column_char(&self) -> char {
220                    unsafe { [<$flname _column_char>](self.inner.widget() as _) as u8 as char }
221                }
222
223                fn set_column_char(&mut self, c: char) {
224                    debug_assert!(c != 0 as char);
225                    let c = if c as i32 > 128 { 128 as char } else { c };
226                    unsafe { [<$flname _set_column_char>](self.inner.widget() as _, c as raw::c_char) }
227                }
228
229                fn column_widths(&self) -> Vec<i32> {
230                    unsafe {
231                        let widths = [<$flname _column_widths>](self.inner.widget() as _);
232                        // Should never throw
233                        assert!(!widths.is_null());
234                        let mut v: Vec<i32> = vec![];
235                        let mut i = 0;
236                        while (*widths.offset(i) != 0) {
237                            v.push(*widths.offset(i));
238                            i += 1;
239                        }
240                        v
241                    }
242                }
243
244                fn set_column_widths(&mut self, arr: &[i32]) {
245                    debug_assert!(!arr.contains(&0), "FLTK uses 0 as a sentinel value for the array/slice. To hide a column, use -1!");
246                    unsafe {
247                        let old = [<$flname _column_widths>](self.inner.widget() as _);
248                        let mut v = arr.to_vec();
249                        v.push(0);
250                        let v = v.into_boxed_slice();
251                        [<$flname _set_column_widths>](self.inner.widget() as _, Box::into_raw(v) as _);
252                        if !old.is_null() && *old.offset(0) != 0 {
253                            let _ = Box::from_raw(old as *mut i32);
254                        }
255                    }
256                }
257
258                fn displayed(&self, line: i32) -> bool {
259                    if line > 0 && line <= self.size() + 1 {
260                    unsafe { [<$flname _displayed>](self.inner.widget() as _, line as i32) != 0 }
261                    } else {
262                        false
263                    }
264                }
265
266                fn make_visible(&mut self, line: i32) {
267                    if line > 0 && line <= self.size() + 1 {
268                        unsafe { [<$flname _make_visible>](self.inner.widget() as _, line as i32) }
269                    }
270                }
271
272                fn vposition(&self) -> i32 {
273                    unsafe { [<$flname _position>](self.inner.widget() as _) as i32 }
274                }
275
276                fn set_vposition(&mut self, pos: i32) {
277                    unsafe { [<$flname _set_position>](self.inner.widget() as _, pos as i32) }
278                }
279
280                fn hposition(&self) -> i32 {
281                    unsafe { [<$flname _hposition>](self.inner.widget() as _) as i32 }
282                }
283
284                fn set_hposition(&mut self, pos: i32) {
285                    unsafe { [<$flname _set_hposition>](self.inner.widget() as _, pos as i32) }
286                }
287
288                fn has_scrollbar(&self) -> $crate::browser::BrowserScrollbar {
289                    unsafe { std::mem::transmute([<$flname _has_scrollbar>](self.inner.widget() as _)) }
290                }
291
292                fn set_has_scrollbar(&mut self, mode: $crate::browser::BrowserScrollbar) {
293                    unsafe {
294                        [<$flname _set_has_scrollbar>](self.inner.widget() as _, mode as raw::c_uchar)
295                    }
296                }
297
298                fn scrollbar_size(&self) -> i32 {
299                    unsafe { [<$flname _scrollbar_size>](self.inner.widget() as _) as i32 }
300                }
301
302                fn set_scrollbar_size(&mut self, new_size: i32) {
303                    unsafe { [<$flname _set_scrollbar_size>](self.inner.widget() as _, new_size as i32) }
304                }
305
306                fn sort(&mut self) {
307                    unsafe { [<$flname _sort>](self.inner.widget() as _) }
308                }
309
310                fn scrollbar(&self) -> $crate::valuator::Scrollbar {
311                    unsafe {
312                        let ptr = [<$flname _scrollbar>](self.inner.widget() as _);
313                        assert!(!ptr.is_null());
314                        $crate::valuator::Scrollbar::from_widget_ptr(
315                            ptr as *mut fltk_sys::widget::Fl_Widget,
316                        )
317                    }
318                }
319
320                fn hscrollbar(&self) -> $crate::valuator::Scrollbar {
321                    unsafe {
322                        let ptr = [<$flname _hscrollbar>](self.inner.widget() as _);
323                        assert!(!ptr.is_null());
324                        $crate::valuator::Scrollbar::from_widget_ptr(
325                            ptr as *mut fltk_sys::widget::Fl_Widget,
326                        )
327                    }
328                }
329
330                fn value(&self) -> i32 {
331                    unsafe { [<$flname _value>](self.inner.widget() as _) as i32 }
332                }
333
334                fn set_data<T: Clone + 'static>(&mut self, line: i32, data: T) {
335                    if line > 0 && line <= self.size() + 1 {
336                    unsafe {
337                            [<$flname _set_data>](self.inner.widget() as _, line, Box::into_raw(Box::from(data)) as _);
338                        }
339                    }
340                }
341
342                unsafe fn data<T: Clone + 'static>(&self, line: i32) -> Option<T> { unsafe {
343                    if line > 0 && line <= self.size() + 1 {
344                        let ptr = [<$flname _data>](self.inner.widget() as _, line);
345                        if ptr.is_null() {
346                            None
347                        } else {
348                            let data = ptr as *const _ as *mut T;
349                            Some((*data).clone())
350                        }
351                    } else {
352                        None
353                    }
354                }}
355
356                fn hide_line(&mut self, line: i32) {
357                    if line > 0 && line <= self.size() + 1 {
358                    unsafe { [<$flname _hide_line>](self.inner.widget() as _, line); }
359                    }
360                }
361
362                fn selected_items(&self) -> Vec<i32> {
363                    let mut temp = vec![];
364                    if self.value() > 0 {
365                        for i in 1..self.size() + 1 {
366                            if self.selected(i) {
367                                temp.push(i);
368                            }
369                        }
370                    }
371                    temp
372                }
373            }
374        }
375    };
376}
377
378pub use impl_browser_ext;