use gtk::glib::Cast;
use gtk::{
ffi::GTK_STYLE_PROVIDER_PRIORITY_APPLICATION,
traits::{BoxExt, OrientableExt, StyleContextExt, WidgetExt},
CssProvider,
};
use crate::styles::{Stylable, Style};
impl Stylable<gtk::Widget> for Style {
fn apply(&self, widget: >k::Widget) {
match self {
Style::none(_) => {}
Style::rounded_full(_) => {
let css = CssProvider::new();
css.load_from_data("* { border-radius: 100%;}");
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::bg(modi, color) => {
let css = CssProvider::new();
let pseudoclass = match modi {
crate::styles::Modifier::none => "",
crate::styles::Modifier::active => ":active",
crate::styles::Modifier::hover => ":hover",
};
css.load_from_data(&format!("*{pseudoclass} {{ background-color: {};}}", color));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::text(_modi, color) => {
let css = CssProvider::new();
css.load_from_data(&format!("* {{ color: {};}}", color));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::m(_modi, margin) => {
widget.set_margin_bottom(*margin as i32);
widget.set_margin_top(*margin as i32);
widget.set_margin_start(*margin as i32);
widget.set_margin_end(*margin as i32);
}
Style::mx(_modi, margin) => {
widget.set_margin_start(*margin as i32);
widget.set_margin_end(*margin as i32);
}
Style::my(_modi, margin) => {
widget.set_margin_start(*margin as i32);
widget.set_margin_end(*margin as i32);
}
Style::mt(_modi, margin) => {
widget.set_margin_top(*margin as i32);
}
Style::mb(_modi, margin) => {
widget.set_margin_bottom(*margin as i32);
}
Style::ml(_modi, margin) => {
widget.set_margin_start(*margin as i32);
}
Style::mr(_modi, margin) => {
widget.set_margin_end(*margin as i32);
}
Style::p(_modi, padding) => {
let css = CssProvider::new();
css.load_from_data(&format!("* {{ padding: {}px;}}", padding));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::px(_modi, padding) => {
let css = CssProvider::new();
css.load_from_data(&format!(
"* {{ padding-left: {0}px; padding-right: {0}px;}}",
padding
));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::py(_modi, padding) => {
let css = CssProvider::new();
css.load_from_data(&format!(
"* {{ padding-top: {0}px; padding-bottom: {0}px;}}",
padding
));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::pt(_modi, padding) => {
let css = CssProvider::new();
css.load_from_data(&format!("* {{ padding-top: {}px;}}", padding));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::pb(_modi, padding) => {
let css = CssProvider::new();
css.load_from_data(&format!("* {{ padding-bottom: {}px;}}", padding));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::pl(_modi, padding) => {
let css = CssProvider::new();
css.load_from_data(&format!("* {{ padding-left: {}px;}}", padding));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::pr(_modi, padding) => {
let css = CssProvider::new();
css.load_from_data(&format!("* {{ padding-right: {}px;}}", padding));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::target(_, can_target) => {
widget.set_can_target(*can_target);
}
Style::vertical(_modi) => {
if let Some(bo) = widget.dynamic_cast_ref::<gtk::Orientable>() {
bo.set_orientation(gtk::Orientation::Vertical)
}
}
Style::horizontal(_modi) => {
if let Some(bo) = widget.dynamic_cast_ref::<gtk::Orientable>() {
bo.set_orientation(gtk::Orientation::Horizontal)
}
}
Style::spacing(_modi, gap) => {
if let Some(bo) = widget.dynamic_cast_ref::<gtk::Box>() {
bo.set_spacing(*gap as i32);
}
}
Style::h(_modi, height) => {
widget.set_height_request(*height as i32);
if let Some(im) = widget.dynamic_cast_ref::<gtk::Image>() {
im.set_pixel_size(*height as i32);
}
}
Style::w(_modi, width) => {
widget.set_width_request(*width as i32);
}
Style::vexpand(_) => widget.set_vexpand(true),
Style::hexpand(_) => widget.set_hexpand(true),
Style::homogeneous(_) => {
if let Some(bo) = widget.dynamic_cast_ref::<gtk::Box>() {
bo.set_homogeneous(true);
}
}
Style::halign(_, align) => match align {
crate::styles::Align::none => {
}
crate::styles::Align::start => widget.set_halign(gtk::Align::Start),
crate::styles::Align::center => widget.set_halign(gtk::Align::Center),
crate::styles::Align::end => widget.set_halign(gtk::Align::End),
},
Style::valign(_, align) => match align {
crate::styles::Align::none => {
}
crate::styles::Align::start => widget.set_valign(gtk::Align::Start),
crate::styles::Align::center => widget.set_valign(gtk::Align::Center),
crate::styles::Align::end => widget.set_valign(gtk::Align::End),
},
Style::border_color(_, color) => {
let css = CssProvider::new();
css.load_from_data(&format!("* {{ border-color: {color}; }}"));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::border(_, b1, b2, b3, b4) => {
let css = CssProvider::new();
css.load_from_data(&format!(
"* {{ border-width: {b1}px {b2}px {b3}px {b4}px; }}"
));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::border_y(_, b) => {
let css = CssProvider::new();
css.load_from_data(&format!("* {{ border-width: {0}px 0px {0}px 0px; }}", b));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::border_x(_, b) => {
let css = CssProvider::new();
css.load_from_data(&format!("* {{ border-width: 0px {0}px 0px {0}px; }}", b));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::border_r(_, b) => {
let css = CssProvider::new();
css.load_from_data(&format!("* {{ border-width: 0px {0}px 0px 0px; }}", b));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::border_l(_, b) => {
let css = CssProvider::new();
css.load_from_data(&format!("* {{ border-width: 0px 0px {0}px 0px; }}", b));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::border_t(_, b) => {
let css = CssProvider::new();
css.load_from_data(&format!("* {{ border-width: {0}px 0px 0px 0px; }}", b));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::border_b(_, b) => {
let css = CssProvider::new();
css.load_from_data(&format!("* {{ border-width: 0px 0px 0px {0}px; }}", b));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
Style::overflow(_, orientation) => {
if let Some(scroll) = widget.downcast_ref::<gtk::ScrolledWindow>() {
match orientation {
crate::styles::Overflow::horizontal => {
scroll.set_vscrollbar_policy(gtk::PolicyType::Never);
}
crate::styles::Overflow::vertical => {
scroll.set_hscrollbar_policy(gtk::PolicyType::Never);
}
crate::styles::Overflow::both => {
scroll.set_hscrollbar_policy(gtk::PolicyType::Automatic);
scroll.set_vscrollbar_policy(gtk::PolicyType::Automatic);
}
crate::styles::Overflow::never => {
scroll.set_hscrollbar_policy(gtk::PolicyType::Never);
scroll.set_vscrollbar_policy(gtk::PolicyType::Never);
}
crate::styles::Overflow::external => {
scroll.set_hscrollbar_policy(gtk::PolicyType::External);
scroll.set_vscrollbar_policy(gtk::PolicyType::External);
}
}
}
}
Style::text_size(_, size) => match size.as_str() {
"xs" => {
let css = CssProvider::new();
css.load_from_data("* { font-size: 0.8rem; }");
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
"l" => widget.add_css_class("title-3"),
"xl" => widget.add_css_class("title-2"),
"xxl" => widget.add_css_class("title-1"),
_ => {
let css = CssProvider::new();
css.load_from_data(&format!("* {{ font-size: {0}; }}", size));
widget
.style_context()
.add_provider(&css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32);
}
},
Style::wrap(_, wrap) => {
if let Some(text) = widget.downcast_ref::<gtk::Label>() {
match wrap {
crate::styles::Wrap::char => {
text.set_wrap(true);
text.set_wrap_mode(gtk::gdk::pango::WrapMode::Char);
}
crate::styles::Wrap::word => {
text.set_wrap(true);
text.set_wrap_mode(gtk::gdk::pango::WrapMode::Word);
}
crate::styles::Wrap::word_char => {
text.set_wrap(true);
text.set_wrap_mode(gtk::gdk::pango::WrapMode::WordChar);
}
}
}
}
Style::ellipsize(_, a) => {
if let Some(text) = widget.downcast_ref::<gtk::Label>() {
match a {
crate::styles::Align::none => {
text.set_ellipsize(gtk::gdk::pango::EllipsizeMode::None);
}
crate::styles::Align::start => {
text.set_ellipsize(gtk::gdk::pango::EllipsizeMode::Start);
}
crate::styles::Align::center => {
text.set_ellipsize(gtk::gdk::pango::EllipsizeMode::Middle);
}
crate::styles::Align::end => {
text.set_ellipsize(gtk::gdk::pango::EllipsizeMode::End);
}
}
}
}
Style::justify(_, justify) => {
if let Some(text) = widget.downcast_ref::<gtk::Label>() {
match justify {
crate::styles::Justify::left => text.set_justify(gtk::Justification::Left),
crate::styles::Justify::right => {
text.set_justify(gtk::Justification::Right)
}
crate::styles::Justify::middle => {
text.set_justify(gtk::Justification::Center)
}
crate::styles::Justify::fill => text.set_justify(gtk::Justification::Fill),
}
}
}
Style::selectable(_) => {
if let Some(text) = widget.downcast_ref::<gtk::Label>() {
text.set_selectable(true);
}
}
}
}
}