use adw::prelude::*; use crate::app::AppState; pub fn build_adjustments_page(state: &AppState) -> adw::NavigationPage { let scrolled = gtk::ScrolledWindow::builder() .hscrollbar_policy(gtk::PolicyType::Never) .vexpand(true) .build(); let content = gtk::Box::builder() .orientation(gtk::Orientation::Vertical) .spacing(12) .margin_top(12) .margin_bottom(12) .margin_start(24) .margin_end(24) .build(); let cfg = state.job_config.borrow(); // Rotate let rotate_group = adw::PreferencesGroup::builder() .title("Orientation") .description("Rotate and flip images") .build(); let rotate_row = adw::ComboRow::builder() .title("Rotate") .subtitle("Rotation applied to all images") .build(); let rotate_model = gtk::StringList::new(&[ "None", "90 clockwise", "180", "270 clockwise", "Auto-orient (from EXIF)", ]); rotate_row.set_model(Some(&rotate_model)); rotate_row.set_selected(cfg.rotation); let flip_row = adw::ComboRow::builder() .title("Flip") .subtitle("Mirror the image") .build(); let flip_model = gtk::StringList::new(&["None", "Horizontal", "Vertical"]); flip_row.set_model(Some(&flip_model)); flip_row.set_selected(cfg.flip); rotate_group.add(&rotate_row); rotate_group.add(&flip_row); content.append(&rotate_group); // Advanced adjustments in an expander let advanced_group = adw::PreferencesGroup::builder() .title("Image Adjustments") .build(); let advanced_expander = adw::ExpanderRow::builder() .title("Advanced Adjustments") .subtitle("Brightness, contrast, saturation, effects") .show_enable_switch(false) .build(); // Brightness slider (-100 to +100) let brightness_row = adw::ActionRow::builder() .title("Brightness") .subtitle("0") .build(); let brightness_scale = gtk::Scale::with_range(gtk::Orientation::Horizontal, -100.0, 100.0, 1.0); brightness_scale.set_value(0.0); brightness_scale.set_hexpand(true); brightness_scale.set_valign(gtk::Align::Center); brightness_scale.set_size_request(200, -1); brightness_scale.set_draw_value(false); let br_label = brightness_row.clone(); brightness_scale.connect_value_changed(move |scale| { br_label.set_subtitle(&format!("{:.0}", scale.value())); }); brightness_row.add_suffix(&brightness_scale); advanced_expander.add_row(&brightness_row); // Contrast slider (-100 to +100) let contrast_row = adw::ActionRow::builder() .title("Contrast") .subtitle("0") .build(); let contrast_scale = gtk::Scale::with_range(gtk::Orientation::Horizontal, -100.0, 100.0, 1.0); contrast_scale.set_value(0.0); contrast_scale.set_hexpand(true); contrast_scale.set_valign(gtk::Align::Center); contrast_scale.set_size_request(200, -1); contrast_scale.set_draw_value(false); let ct_label = contrast_row.clone(); contrast_scale.connect_value_changed(move |scale| { ct_label.set_subtitle(&format!("{:.0}", scale.value())); }); contrast_row.add_suffix(&contrast_scale); advanced_expander.add_row(&contrast_row); // Saturation slider (-100 to +100) let saturation_row = adw::ActionRow::builder() .title("Saturation") .subtitle("0") .build(); let saturation_scale = gtk::Scale::with_range(gtk::Orientation::Horizontal, -100.0, 100.0, 1.0); saturation_scale.set_value(0.0); saturation_scale.set_hexpand(true); saturation_scale.set_valign(gtk::Align::Center); saturation_scale.set_size_request(200, -1); saturation_scale.set_draw_value(false); let sat_label = saturation_row.clone(); saturation_scale.connect_value_changed(move |scale| { sat_label.set_subtitle(&format!("{:.0}", scale.value())); }); saturation_row.add_suffix(&saturation_scale); advanced_expander.add_row(&saturation_row); // Sharpen after resize let sharpen_row = adw::SwitchRow::builder() .title("Sharpen after resize") .subtitle("Apply subtle sharpening to resized images") .active(false) .build(); advanced_expander.add_row(&sharpen_row); // Grayscale let grayscale_row = adw::SwitchRow::builder() .title("Grayscale") .subtitle("Convert images to black and white") .active(false) .build(); advanced_expander.add_row(&grayscale_row); // Sepia let sepia_row = adw::SwitchRow::builder() .title("Sepia") .subtitle("Apply a warm vintage tone") .active(false) .build(); advanced_expander.add_row(&sepia_row); advanced_group.add(&advanced_expander); content.append(&advanced_group); drop(cfg); // Wire signals { let jc = state.job_config.clone(); rotate_row.connect_selected_notify(move |row| { jc.borrow_mut().rotation = row.selected(); }); } { let jc = state.job_config.clone(); flip_row.connect_selected_notify(move |row| { jc.borrow_mut().flip = row.selected(); }); } scrolled.set_child(Some(&content)); let clamp = adw::Clamp::builder() .maximum_size(600) .child(&scrolled) .build(); adw::NavigationPage::builder() .title("Adjustments") .tag("step-adjustments") .child(&clamp) .build() }