use crate::enums::{Align, CallbackTrigger, Color, Damage, Event, Font, FrameType, LabelType};
use crate::image::Image;
use crate::prelude::*;
use crate::utils::FlString;
use crate::widget::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) -> i32 {
assert!(!self.was_deleted());
unsafe { Fl_Scroll_xposition(self.inner) as i32 }
}
pub fn yposition(&self) -> i32 {
assert!(!self.was_deleted());
unsafe { Fl_Scroll_yposition(self.inner) as i32 }
}
pub fn scroll_to(&mut self, from: i32, to: i32) {
assert!(!self.was_deleted());
unsafe { Fl_Scroll_scroll_to(self.inner, from as i32, to as i32) }
}
pub fn scrollbar_size(&self) -> i32 {
assert!(!self.was_deleted());
unsafe { Fl_Scroll_scrollbar_size(self.inner) as i32 }
}
pub fn set_scrollbar_size(&mut self, new_size: i32) {
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;
if children == 0 {
return;
}
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 i32).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<T: Into<Option<&'static str>>>(x: i32, y: i32, w: i32, h: i32, label: T) -> 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 i32).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<T: Into<Option<&'static str>>>(x: i32, y: i32, w: i32, h: i32, label: T) -> 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 i32).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
}
}
pub struct Column {
p: Pack,
}
impl Column {
pub fn default() -> Self {
let mut p = Pack::default().size_of_parent().center_of_parent();
p.set_type(PackType::Vertical);
p.end();
Column { p }
}
pub fn add<W: WidgetExt>(&mut self, w: &W) {
self.p.add(w);
self.p.auto_layout();
}
}
impl Deref for Column {
type Target = Pack;
fn deref(&self) -> &Self::Target {
&self.p
}
}
impl DerefMut for Column {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.p
}
}
pub struct Row {
p: Pack,
}
impl Row {
pub fn default() -> Self {
let mut p = Pack::default().size_of_parent().center_of_parent();
p.set_type(PackType::Horizontal);
p.end();
Row { p }
}
pub fn add<W: WidgetExt>(&mut self, w: &W) {
self.p.add(w);
self.p.auto_layout();
}
}
impl Deref for Row {
type Target = Pack;
fn deref(&self) -> &Self::Target {
&self.p
}
}
impl DerefMut for Row {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.p
}
}