rsproject/src/components/setting_item/mod.rs
2024-02-27 15:17:43 +08:00

112 lines
3.6 KiB
Rust

use adw::glib::gobject_ffi::GValue;
use adw::glib::GString;
use adw::prelude::*;
use gtk::prelude::*;
use gtk::{StringList, Widget};
use relm4::{factory::FactoryView, gtk, prelude::*, FactorySender, RelmObjectExt};
use std::cell::{Cell, RefCell};
use std::rc::Rc;
#[derive(Debug)]
pub enum Msg {}
#[derive(Debug)]
pub enum OutputMsg {}
pub enum SettingType {
Select(Vec<&'static str>, Option<Box<dyn Fn(usize)>>),
Action,
Entry(
Option<String>,
Option<Box<dyn Fn(&str) -> bool>>,
Option<Box<dyn Fn(&str)>>,
),
Switch(bool, Option<Rc<Cell<bool>>>),
Spin(f64, f64, f64, f64, Option<Rc<Cell<f64>>>),
}
pub struct SettingItem {
title: String,
pub _type: SettingType,
}
impl SettingItem {
pub fn new(title: String, _type: SettingType) -> Self {
Self { title, _type }
}
pub fn widget(&mut self) -> Widget {
(match &mut self._type {
SettingType::Select(selects, selected) => {
let w = adw::ComboRow::builder().title(&self.title).build();
if let Some(selected) = selected.take() {
w.connect_selected_notify(move |s| {
selected(s.selected() as usize);
});
}
let model = StringList::new(selects.as_ref());
w.set_model(Some(&model));
w.upcast::<Widget>()
}
SettingType::Action => adw::EntryRow::builder()
.title(&self.title)
.build()
.upcast::<Widget>(),
SettingType::Entry(text, f, buffer) => {
let w = adw::EntryRow::new();
w.set_title(&self.title);
if let Some(text) = text {
w.set_text(text);
}
if let Some(f) = f.take() {
let mut buffer = buffer.take();
w.connect_text_notify(move |s| {
let text = s.text();
if !f(text.as_str()) {
s.add_css_class("error");
return;
} else {
s.remove_css_class("error");
}
if let Some(buffer) = buffer.as_ref() {
buffer(text.as_str());
}
});
}
w.upcast::<Widget>()
}
SettingType::Switch(t, v) => {
let w = adw::SwitchRow::new();
w.set_title(&self.title);
w.set_active(*t);
if let Some(v) = v {
let v = v.clone();
w.connect_active_notify(move |s| {
v.set(s.is_active());
});
}
w.upcast::<Widget>()
}
SettingType::Spin(min, max, clamb, value, v) => {
let w = adw::SpinRow::new(
Some(&gtk::Adjustment::new(*value, *min, *max, *clamb, 0.0, 0.0)),
*clamb,
0,
);
w.set_numeric(true);
if let Some(v) = v {
let v = v.clone();
w.connect_value_notify(move |s| {
v.set(s.value());
});
}
// w.set_range(*min, *max);
w.set_value(*value);
w.set_title(&self.title);
w.upcast::<Widget>()
}
})
}
}