use crate::image::Image;
pub use crate::prelude::*;
use crate::widget::*;
use fltk_sys::group::*;
use std::{
ffi::{CStr, CString},
mem,
ops::{Deref, DerefMut},
os::raw,
};
#[derive(WidgetBase, WidgetExt, GroupExt, Debug)]
pub struct Group {
_inner: *mut Fl_Group,
_tracker: *mut fltk_sys::fl::Fl_Widget_Tracker,
}
impl Group {
pub fn current() -> Box<dyn GroupExt> {
unsafe {
let ptr = Fl_Group_current();
assert!(!ptr.is_null());
Box::new(Group::from_widget_ptr(ptr as _))
}
}
}
#[derive(WidgetBase, WidgetExt, GroupExt, Debug)]
pub struct Pack {
_inner: *mut Fl_Pack,
_tracker: *mut fltk_sys::fl::Fl_Widget_Tracker,
}
#[repr(i32)]
#[derive(WidgetType, Debug, Copy, Clone, PartialEq)]
pub enum PackType {
Vertical = 0,
Horizontal = 1,
}
#[derive(WidgetBase, WidgetExt, GroupExt, Debug)]
pub struct Scroll {
_inner: *mut Fl_Scroll,
_tracker: *mut fltk_sys::fl::Fl_Widget_Tracker,
}
#[repr(i32)]
#[derive(WidgetType, Debug, Copy, Clone, PartialEq)]
pub enum ScrollType {
None = 0,
Horizontal = 1,
Vertical = 2,
Both = 3,
AlwaysOn = 4,
HorizontalAlways = 5,
VerticalAlways = 6,
BothAlways = 7,
}
impl Scroll {
pub fn scrollbar(&self) -> impl ValuatorExt {
assert!(!self.was_deleted());
unsafe {
let ptr = Fl_Scroll_scrollbar(self._inner);
assert!(!ptr.is_null());
crate::valuator::Scrollbar::from_widget_ptr(ptr as *mut fltk_sys::widget::Fl_Widget)
}
}
pub fn hscrollbar(&self) -> impl ValuatorExt {
assert!(!self.was_deleted());
unsafe {
let ptr = Fl_Scroll_hscrollbar(self._inner);
assert!(!ptr.is_null());
crate::valuator::Scrollbar::from_widget_ptr(ptr as *mut fltk_sys::widget::Fl_Widget)
}
}
pub fn xposition(&self) -> u32 {
assert!(!self.was_deleted());
unsafe { Fl_Scroll_xposition(self._inner) as u32 }
}
pub fn yposition(&self) -> u32 {
assert!(!self.was_deleted());
unsafe { Fl_Scroll_yposition(self._inner) as u32 }
}
pub fn scroll_to(&mut self, from: u32, to: u32) {
debug_assert!(
from <= std::isize::MAX as u32,
"u32 entries have to be < std::isize::MAX for compatibility!"
);
debug_assert!(
to <= std::isize::MAX as u32,
"u32 entries have to be < std::isize::MAX for compatibility!"
);
assert!(!self.was_deleted());
unsafe { Fl_Scroll_scroll_to(self._inner, from as i32, to as i32) }
}
pub fn scrollbar_size(&self) -> u32 {
assert!(!self.was_deleted());
unsafe { Fl_Scroll_scrollbar_size(self._inner) as u32 }
}
pub fn set_scrollbar_size(&mut self, new_size: u32) {
debug_assert!(
new_size <= std::isize::MAX as u32,
"u32 entries have to be < std::isize::MAX for compatibility!"
);
assert!(!self.was_deleted());
unsafe { Fl_Scroll_set_scrollbar_size(self._inner, new_size as i32) }
}
}
#[derive(WidgetBase, WidgetExt, GroupExt, Debug)]
pub struct Tabs {
_inner: *mut Fl_Tabs,
_tracker: *mut fltk_sys::fl::Fl_Widget_Tracker,
}
impl Tabs {
pub fn value(&mut self) -> Option<impl GroupExt> {
assert!(!self.was_deleted());
unsafe {
let ptr = Fl_Tabs_value(self._inner);
if ptr.is_null() {
None
} else {
Some(Group::from_widget_ptr(
ptr as *mut fltk_sys::widget::Fl_Widget,
))
}
}
}
pub fn set_value<Grp: GroupExt>(&mut self, w: &Grp) -> Result<(), FltkError> {
assert!(!self.was_deleted());
unsafe {
match Fl_Tabs_set_value(
self._inner,
w.as_widget_ptr() as *mut fltk_sys::group::Fl_Widget,
) {
0 => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
_ => Ok(()),
}
}
}
pub fn push(&self) -> Option<impl GroupExt> {
assert!(!self.was_deleted());
unsafe {
let ptr = Fl_Tabs_push(self._inner);
if ptr.is_null() {
None
} else {
Some(Group::from_widget_ptr(
ptr as *mut fltk_sys::widget::Fl_Widget,
))
}
}
}
pub fn set_push<Grp: GroupExt>(&mut self, w: &Grp) -> Result<(), FltkError> {
assert!(!self.was_deleted());
unsafe {
match Fl_Tabs_set_push(
self._inner,
w.as_widget_ptr() as *mut fltk_sys::group::Fl_Widget,
) {
0 => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
_ => Ok(()),
}
}
}
pub fn client_area(&mut self) -> (i32, i32, i32, i32) {
assert!(!self.was_deleted());
unsafe {
let mut i1 = 0;
let mut i2 = 0;
let mut i3 = 0;
let mut i4 = 0;
Fl_Tabs_client_area(self._inner, &mut i1, &mut i2, &mut i3, &mut i4);
(i1, i2, i3, i4)
}
}
pub fn set_tab_align(&mut self, a: Align) {
assert!(!self.was_deleted());
unsafe { Fl_Tabs_set_tab_align(self._inner, a.bits() as i32) }
}
pub fn tab_align(&self) -> Align {
assert!(!self.was_deleted());
unsafe { mem::transmute(Fl_Tabs_tab_align(self._inner)) }
}
}
#[derive(WidgetBase, WidgetExt, GroupExt, Debug)]
pub struct Tile {
_inner: *mut Fl_Tile,
_tracker: *mut fltk_sys::fl::Fl_Widget_Tracker,
}
#[derive(WidgetBase, WidgetExt, GroupExt, Debug)]
pub struct Wizard {
_inner: *mut Fl_Wizard,
_tracker: *mut fltk_sys::fl::Fl_Widget_Tracker,
}
impl Wizard {
pub fn next(&mut self) {
assert!(!self.was_deleted());
unsafe { Fl_Wizard_next(self._inner) }
}
pub fn prev(&mut self) {
assert!(!self.was_deleted());
unsafe { Fl_Wizard_prev(self._inner) }
}
pub fn current_widget(&mut self) -> Box<dyn WidgetExt> {
unsafe {
assert!(!self.was_deleted());
Box::new(Widget::from_widget_ptr(
Fl_Wizard_value(self._inner) as *mut fltk_sys::widget::Fl_Widget
))
}
}
pub fn set_current_widget<W: WidgetExt>(&mut self, w: &W) {
unsafe {
assert!(!self.was_deleted());
Fl_Wizard_set_value(
self._inner,
w.as_widget_ptr() as *mut fltk_sys::group::Fl_Widget,
)
}
}
}
#[derive(WidgetBase, WidgetExt, GroupExt, Debug)]
pub struct ColorChooser {
_inner: *mut Fl_Color_Chooser,
_tracker: *mut fltk_sys::fl::Fl_Widget_Tracker,
}
impl ColorChooser {
pub fn rgb_color(&self) -> (u8, u8, u8) {
unsafe {
assert!(!self.was_deleted());
let r = (Fl_Color_Chooser_r(self._inner) * 255.0) as u8;
let g = (Fl_Color_Chooser_g(self._inner) * 255.0) as u8;
let b = (Fl_Color_Chooser_b(self._inner) * 255.0) as u8;
(r, g, b)
}
}
pub fn hex_color(&self) -> u32 {
assert!(!self.was_deleted());
let (r, g, b) = self.rgb_color();
crate::utils::rgb2hex(r, g, b)
}
}
impl Pack {
pub fn spacing(&self) -> i32 {
assert!(!self.was_deleted());
unsafe { Fl_Pack_spacing(self._inner) }
}
pub fn set_spacing(&mut self, spacing: i32) {
unsafe {
assert!(!self.was_deleted());
Fl_Pack_set_spacing(self._inner, spacing);
}
}
pub fn auto_layout(&mut self) {
let children = self.children() as i32;
let spacing = self.spacing() * (children - 1);
let t = self.get_type::<PackType>();
let w = (self.width() - spacing) / children;
let h = (self.height() - spacing) / children;
for i in 0..children {
let mut c = self.child(i as u32).unwrap();
let c_w = c.width();
let c_h = c.height();
if t == PackType::Vertical {
c.set_size(c_w, h);
} else {
c.set_size(w, c_h);
}
}
}
}
#[derive(Debug, Clone)]
pub struct VGrid {
vpack: Pack,
rows: i32,
cols: i32,
current: i32,
}
impl VGrid {
pub fn new(x: i32, y: i32, w: i32, h: i32, label: &str) -> VGrid {
let vpack = Pack::new(x, y, w, h, label);
vpack.end();
VGrid {
vpack,
rows: 1,
cols: 1,
current: 0,
}
}
pub fn set_params(&mut self, rows: i32, cols: i32, spacing: i32) {
self.vpack.set_spacing(spacing);
let rows = if rows < 1 { 1 } else { rows };
let cols = if cols < 1 { 1 } else { cols };
self.rows = rows;
self.cols = cols;
for _ in 0..rows {
let mut p = Pack::new(0, 0, self.vpack.width(), 0, "");
p.set_type(PackType::Horizontal);
p.set_spacing(spacing);
p.end();
self.vpack.add(&p);
}
}
pub fn add<W: WidgetExt>(&mut self, w: &W) {
let rem = self.current / self.cols;
if rem < self.rows {
let hpack = self.vpack.child(rem as u32).unwrap();
let mut hpack = unsafe { Pack::from_widget_ptr(hpack.as_widget_ptr()) };
hpack.end();
hpack.add(w);
hpack.auto_layout();
self.vpack.auto_layout();
self.current += 1;
}
}
}
impl Deref for VGrid {
type Target = Pack;
fn deref(&self) -> &Self::Target {
&self.vpack
}
}
impl DerefMut for VGrid {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.vpack
}
}
#[derive(Debug, Clone)]
pub struct HGrid {
hpack: Pack,
rows: i32,
cols: i32,
current: i32,
}
impl HGrid {
pub fn new(x: i32, y: i32, w: i32, h: i32, label: &str) -> HGrid {
let mut hpack = Pack::new(x, y, w, h, label);
hpack.set_type(PackType::Horizontal);
hpack.end();
HGrid {
hpack,
rows: 1,
cols: 1,
current: 0,
}
}
pub fn set_params(&mut self, rows: i32, cols: i32, spacing: i32) {
self.hpack.set_spacing(spacing);
let rows = if rows < 1 { 1 } else { rows };
let cols = if cols < 1 { 1 } else { cols };
self.rows = rows;
self.cols = cols;
for _ in 0..cols {
let mut p = Pack::new(0, 0, 0, self.hpack.height(), "");
p.set_spacing(spacing);
p.end();
self.hpack.add(&p);
}
}
pub fn add<W: WidgetExt>(&mut self, w: &W) {
let rem = self.current / self.rows;
if rem < self.cols {
let vpack = self.hpack.child(rem as u32).unwrap();
let mut vpack = unsafe { Pack::from_widget_ptr(vpack.as_widget_ptr()) };
vpack.end();
vpack.add(w);
vpack.auto_layout();
self.hpack.auto_layout();
self.current += 1;
}
}
}
impl Deref for HGrid {
type Target = Pack;
fn deref(&self) -> &Self::Target {
&self.hpack
}
}
impl DerefMut for HGrid {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.hpack
}
}