guth 0.2.13

Native Rust desktop file manager for fast, bounded local file workflows.
Documentation
use eframe::egui::{self, Color32, Pos2, Rect, RichText, Rounding, Sense, Stroke, Vec2};

pub fn panel_heading(ui: &mut egui::Ui, tag: &str, title: &str) {
    let text = ui
        .visuals()
        .override_text_color
        .unwrap_or_else(|| Color32::from_rgb(244, 244, 244));
    let muted = ui.visuals().widgets.inactive.fg_stroke.color;
    let border = ui.visuals().widgets.inactive.bg_stroke.color;
    ui.vertical(|ui| {
        ui.label(RichText::new(tag).size(11.0).color(muted));
        ui.label(RichText::new(title).size(16.0).strong().color(text));
    });
    ui.add_space(2.0);
    let (rect, _) = ui.allocate_exact_size(Vec2::new(ui.available_width(), 1.0), Sense::hover());
    ui.painter().line_segment(
        [rect.left_center(), rect.right_center()],
        Stroke::new(1.0, border),
    );
}

pub fn field_label(ui: &mut egui::Ui, label: &str) {
    let muted = ui.visuals().widgets.inactive.fg_stroke.color;
    ui.label(RichText::new(label).size(11.0).color(muted));
}

pub fn muted_label(ui: &mut egui::Ui, text: impl Into<String>) {
    let muted = ui.visuals().widgets.inactive.fg_stroke.color;
    ui.label(RichText::new(text.into()).size(10.0).color(muted));
}

pub fn paint_background(
    ui: &mut egui::Ui,
    fill: Color32,
    background_image: Option<&egui::TextureHandle>,
    background_opacity: f32,
) {
    let rect = ui.max_rect();
    let painter = ui.painter().clone();
    painter.rect_filled(rect, Rounding::ZERO, fill);

    if let Some(texture) = background_image {
        let alpha = (background_opacity.clamp(0.0, 0.36) * 255.0).round() as u8;
        if alpha > 0 {
            painter.image(
                texture.id(),
                cover_rect(rect, texture.size_vec2()),
                Rect::from_min_max(Pos2::ZERO, Pos2::new(1.0, 1.0)),
                Color32::from_white_alpha(alpha),
            );
            let light = u16::from(fill.r()) + u16::from(fill.g()) + u16::from(fill.b()) > 410;
            let veil_strength = (background_opacity / 0.36).clamp(0.0, 1.0);
            painter.rect_filled(
                rect,
                Rounding::ZERO,
                if light {
                    Color32::from_white_alpha((96.0 * veil_strength).round() as u8)
                } else {
                    Color32::from_black_alpha((112.0 * veil_strength).round() as u8)
                },
            );
        }
    }
}

fn cover_rect(target: Rect, image_size: Vec2) -> Rect {
    if image_size.x <= 0.0 || image_size.y <= 0.0 {
        return target;
    }
    let scale = (target.width() / image_size.x).max(target.height() / image_size.y);
    let size = image_size * scale;
    Rect::from_center_size(target.center(), size)
}