fltk-extras 0.1.3

Some extra widgets for fltk-rs
Documentation
use crate::styles::colors::*;
use fltk::{enums::*, prelude::*, *};
use std::sync::{
    atomic::{AtomicBool, AtomicI32, Ordering},
    Arc,
};

#[derive(Debug, Clone)]
pub struct Dial {
    dial: valuator::FillDial,
    value: Arc<AtomicI32>,
    modifiable: Arc<AtomicBool>,
}

impl Default for Dial {
    fn default() -> Self {
        Dial::new(0, 0, 0, 0, "")
    }
}

impl Dial {
    pub fn new(x: i32, y: i32, w: i32, h: i32, label: &str) -> Self {
        let mut dial = valuator::FillDial::new(x, y, w, h, None)
            .with_label(label)
            .with_align(Align::Top);
        dial.set_label_size(app::font_size() + 2);
        dial.set_frame(FrameType::NoBox);
        dial.set_color(Color::color_average(dial.color(), Color::Foreground, 0.9));
        dial.set_selection_color(RED);
        let value = Arc::new(AtomicI32::new(0));
        let value_c = value.clone();
        dial.draw(move |w| {
            draw::set_draw_color(w.parent().unwrap().color());
            draw::draw_pie(
                w.x() + (w.w() / 6),
                w.y() + (w.h() / 6),
                w.w() * 2 / 3,
                w.h() * 2 / 3,
                0.,
                360.,
            );
            draw::set_font(Font::Helvetica, 16);
            draw::set_draw_color(w.label_color());
            draw::draw_text2(
                &value_c.load(Ordering::Relaxed).to_string(),
                w.x(),
                w.y(),
                w.w(),
                w.h(),
                Align::Center,
            );
        });
        let modifiable = Arc::new(AtomicBool::new(true));
        let mod_c = modifiable.clone();
        let val_c = value.clone();
        dial.set_callback(move |d| {
            if mod_c.load(Ordering::Relaxed) {
                val_c.store((d.value() * 100.) as i32, Ordering::Relaxed);
            } else {
                d.set_value(val_c.load(Ordering::Relaxed) as f64 / 100.)
            }
        });
        Self {
            dial,
            value,
            modifiable,
        }
    }
    pub fn set_value(&mut self, val: i32) {
        self.value.store(val, Ordering::Relaxed);
        self.dial.set_value(val as f64 / 100.);
    }
    pub fn modifiable(&mut self, val: bool) {
        self.modifiable.store(val, Ordering::Relaxed);
    }
    pub fn set_callback<F: 'static + FnMut(&mut Self)>(&mut self, mut cb: F) {
        let mut s = self.clone();
        self.dial.set_callback(move |_| {
            cb(&mut s);
            app::redraw();
        });
    }
}

fltk::widget_extends!(Dial, valuator::FillDial, dial);

#[derive(Debug, Clone)]
pub struct HalfDial {
    main_wid: group::Flex,
    value: Arc<AtomicI32>,
    value_frame: frame::Frame,
}

impl Default for HalfDial {
    fn default() -> Self {
        HalfDial::new(0, 0, 0, 0, "")
    }
}

impl HalfDial {
    pub fn new(x: i32, y: i32, w: i32, h: i32, label: &str) -> Self {
        let value = AtomicI32::new(0);
        let mut main_wid = group::Flex::new(x, y, w, h, None)
            .with_label(label)
            .with_align(Align::Top)
            .column();
        main_wid.set_label_size(app::font_size() + 3);
        let mut value_frame = frame::Frame::default().with_label("0");
        value_frame.set_label_size(app::font_size() + 12);
        main_wid.set_selection_color(RED);
        main_wid.end();
        main_wid.set_size(&value_frame, 30);
        let value = Arc::new(value);
        let value_c = value.clone();
        main_wid.draw(move |w| {
            let parent = w.parent().unwrap();
            let parent_col = parent.color();
            draw::set_draw_color(Color::color_average(parent_col, Color::Foreground, 0.9));
            draw::draw_pie(w.x(), w.y(), w.w(), w.h(), -45., 225.);
            draw::set_draw_color(w.selection_color());
            let val = value_c.load(Ordering::Relaxed);
            let val = if val > 100 { 100 } else { val };
            draw::draw_pie(
                w.x(),
                w.y(),
                w.w(),
                w.h(),
                (100 - val) as f64 * 2.7 - 45.,
                225.,
            );
            draw::set_draw_color(parent_col);
            draw::draw_pie(
                w.x() + (w.w() / 4),
                w.y() + (w.h() / 4),
                w.w() * 2 / 4,
                w.h() * 2 / 4,
                0.,
                360.,
            );
            w.draw_children();
        });
        main_wid.resize_callback({
            let mut value_frame = value_frame.clone();
            move |_, x, y, w, _h| {
                value_frame.resize(x, y + 80, w, 40);
            }
        });
        Self {
            main_wid,
            value,
            value_frame,
        }
    }
    pub fn set_value(&mut self, val: i32) {
        self.value.store(val, Ordering::Relaxed);
        self.value_frame.set_label(&val.to_string());
        self.main_wid.redraw();
    }
}

widget_extends!(HalfDial, group::Flex, main_wid);