diff --git a/crates/ui-egui/src/content_ui.rs b/crates/ui-egui/src/content_ui.rs index 38f63587cb..148830e010 100644 --- a/crates/ui-egui/src/content_ui.rs +++ b/crates/ui-egui/src/content_ui.rs @@ -561,21 +561,21 @@ pub(crate) fn format_panel(ui: &mut egui::Ui, t: &Tokens, style: &AddedText) -> ui.selectable_value(&mut s.family, f, f.label()); } #[cfg(not(target_arch = "wasm32"))] - if let Some(installed) = crate::files::installed_font_files(ui.ctx()) { - if !installed.is_empty() { - ui.separator(); - ui.label(egui::RichText::new(tl!("Installed fonts")).weak().small()); - for font in &installed { - let fam = if font.family.eq_ignore_ascii_case("times") || font.face.to_ascii_lowercase().contains("times") { - FontFamily::Times - } else if font.family.eq_ignore_ascii_case("courier") || font.face.to_ascii_lowercase().contains("courier") { - FontFamily::Courier - } else { - FontFamily::Helvetica - }; - if ui.selectable_label(s.family == fam, &font.face).clicked() { - s.family = fam; - } + if let Some(installed) = crate::files::installed_font_files(ui.ctx()) + && !installed.is_empty() + { + ui.separator(); + ui.label(egui::RichText::new(tl!("Installed fonts")).weak().small()); + for font in &installed { + let fam = if font.family.eq_ignore_ascii_case("times") || font.face.to_ascii_lowercase().contains("times") { + FontFamily::Times + } else if font.family.eq_ignore_ascii_case("courier") || font.face.to_ascii_lowercase().contains("courier") { + FontFamily::Courier + } else { + FontFamily::Helvetica + }; + if ui.selectable_label(s.family == fam, &font.face).clicked() { + s.family = fam; } } } @@ -621,10 +621,10 @@ pub(crate) fn format_panel(ui: &mut egui::Ui, t: &Tokens, style: &AddedText) -> } }); let show_palette_id = ui.id().with("show-palette-added"); - if ui.data(|d| d.get_temp::(show_palette_id)).unwrap_or(false) { - if let Some(picked) = crate::comments::swatch_grid(ui, Some(s.color)) { - s.color = picked; - } + if ui.data(|d| d.get_temp::(show_palette_id)).unwrap_or(false) + && let Some(picked) = crate::comments::swatch_grid(ui, Some(s.color)) + { + s.color = picked; } ui.horizontal(|ui| { let b_resp = ui.selectable_label(s.bold, egui::RichText::new("T").strong().size(14.0)); diff --git a/crates/ui-egui/src/edit_text_ui.rs b/crates/ui-egui/src/edit_text_ui.rs index 73d6eaaf41..282ab3eac9 100644 --- a/crates/ui-egui/src/edit_text_ui.rs +++ b/crates/ui-egui/src/edit_text_ui.rs @@ -179,9 +179,7 @@ pub fn toggle_bullet_list(text: &mut String) -> bool { } else { new_text.push_str(line); } - } else if trimmed.is_empty() { - new_text.push_str(line); - } else if trimmed.starts_with("• ") { + } else if trimmed.is_empty() || trimmed.starts_with("• ") { new_text.push_str(line); } else { new_text.push_str("• "); @@ -218,11 +216,13 @@ pub fn toggle_numbered_list(text: &mut String) -> bool { } let t = line.trim_start(); if all_numbered { - if let Some(dot_idx) = t.find('.') { - if dot_idx > 0 && t[..dot_idx].chars().all(|c| c.is_ascii_digit()) && t[dot_idx..].starts_with(". ") { - new_text.push_str(&t[dot_idx + 2..]); - continue; - } + if let Some(dot_idx) = t.find('.') + && dot_idx > 0 + && t[..dot_idx].chars().all(|c| c.is_ascii_digit()) + && t[dot_idx..].starts_with(". ") + { + new_text.push_str(&t[dot_idx + 2..]); + continue; } new_text.push_str(line); } else if t.is_empty() { @@ -905,10 +905,11 @@ pub(crate) fn image_input( painter.rect_stroke(b, CornerRadius::ZERO, Stroke::new(1.5, ACCENT), egui::StrokeKind::Outside); draw_handles(b); } - if allow_interaction && let Some(p) = hover_pos { - if let Some(&h) = all_handles.iter().find(|&&h| handle_pos(b, h).distance(p) < 8.0) { - ui.ctx().set_cursor_icon(cursor_for(h)); - } + if allow_interaction + && let Some(p) = hover_pos + && let Some(&h) = all_handles.iter().find(|&&h| handle_pos(b, h).distance(p) < 8.0) + { + ui.ctx().set_cursor_icon(cursor_for(h)); } } @@ -927,10 +928,10 @@ pub(crate) fn image_input( if let Some(s) = view.image_selection.as_mut() { s.drag = Some(ImageDrag { start: o, target: DragTarget::CropHandle(h), initial_rect: active_crop }); } - } else if active_crop.contains(o) { - if let Some(s) = view.image_selection.as_mut() { - s.drag = Some(ImageDrag { start: o, target: DragTarget::Move, initial_rect: active_crop }); - } + } else if active_crop.contains(o) + && let Some(s) = view.image_selection.as_mut() + { + s.drag = Some(ImageDrag { start: o, target: DragTarget::Move, initial_rect: active_crop }); } } else { let hit_handle = all_handles.iter().copied().find(|&h| handle_pos(b, h).distance(o) < 8.0); @@ -938,10 +939,10 @@ pub(crate) fn image_input( if let Some(s) = view.image_selection.as_mut() { s.drag = Some(ImageDrag { start: o, target: DragTarget::Handle(h), initial_rect: b }); } - } else if image_contains(i, o) { - if let Some(s) = view.image_selection.as_mut() { - s.drag = Some(ImageDrag { start: o, target: DragTarget::Move, initial_rect: b }); - } + } else if image_contains(i, o) + && let Some(s) = view.image_selection.as_mut() + { + s.drag = Some(ImageDrag { start: o, target: DragTarget::Move, initial_rect: b }); } } } @@ -991,10 +992,10 @@ pub(crate) fn image_input( if let Some(s) = view.image_selection.as_mut() { s.crop_rect = Some(new_crop); } - if resp.drag_stopped() || !ui.input(|i| i.pointer.primary_down()) { - if let Some(s) = view.image_selection.as_mut() { - s.drag = None; - } + if (resp.drag_stopped() || !ui.input(|i| i.pointer.primary_down())) + && let Some(s) = view.image_selection.as_mut() + { + s.drag = None; } ui.ctx().set_cursor_icon(match drag.target { DragTarget::CropHandle(h) => cursor_for(h), diff --git a/crates/ui-egui/src/panels.rs b/crates/ui-egui/src/panels.rs index 499feaab59..6f9758ac9a 100644 --- a/crates/ui-egui/src/panels.rs +++ b/crates/ui-egui/src/panels.rs @@ -400,18 +400,18 @@ fn format_section(app: &mut PdfCraftApp, ui: &mut egui::Ui, t: &Tokens) { let is_current = ed.font_resource.as_ref().is_some_and(|r| { font_choices.iter().any(|f| &f.resource == r && f.face == font.face) }); - if ui.selectable_label(is_current, &font.face).clicked() { - if let Ok(bytes) = std::fs::read(&font.path) { - let edit = pdfcraft_engine::Edit::RegisterTextFont { page: ed.page, bytes: std::sync::Arc::new(bytes.clone()) }; - if app.apply_edit(edit) { - if let Some(doc) = app.session.get(app.views[i].id) { - if let Some(f) = doc.text_editor_fonts(ed.page).into_iter().find(|f| f.bytes == bytes) { - ed.font_resource = Some(f.resource); - changed = true; - } - ed.fonts = crate::edit_text_ui::install_source_fonts(ui.ctx(), doc, ed.page); - } + if ui.selectable_label(is_current, &font.face).clicked() + && let Ok(bytes) = std::fs::read(&font.path) + { + let edit = pdfcraft_engine::Edit::RegisterTextFont { page: ed.page, bytes: std::sync::Arc::new(bytes.clone()) }; + if app.apply_edit(edit) + && let Some(doc) = app.session.get(app.views[i].id) + { + if let Some(f) = doc.text_editor_fonts(ed.page).into_iter().find(|f| f.bytes == bytes) { + ed.font_resource = Some(f.resource); + changed = true; } + ed.fonts = crate::edit_text_ui::install_source_fonts(ui.ctx(), doc, ed.page); } } } @@ -475,11 +475,11 @@ fn format_section(app: &mut PdfCraftApp, ui: &mut egui::Ui, t: &Tokens) { // Color Swatch Grid (when toggled or open) let show_palette_id = ui.id().with("show-palette"); - if ui.data(|d| d.get_temp::(show_palette_id)).unwrap_or(false) { - if let Some(picked) = crate::comments::swatch_grid(ui, Some(ed.look.color)) { - ed.look.color = picked; - changed = true; - } + if ui.data(|d| d.get_temp::(show_palette_id)).unwrap_or(false) + && let Some(picked) = crate::comments::swatch_grid(ui, Some(ed.look.color)) + { + ed.look.color = picked; + changed = true; } // Formatting Buttons: Bold, Italic, Underline, Superscript, Subscript diff --git a/parity/acrobat-features.toml b/parity/acrobat-features.toml index 359a71e9a6..0e73ae2150 100644 --- a/parity/acrobat-features.toml +++ b/parity/acrobat-features.toml @@ -2127,11 +2127,11 @@ title = "Arrange objects (bring forward, send backward)" area = "C" tier = "P1" milestone = "M7" -status = "planned" +status = "partial" commands = [] -tools = [] -evidence = [] -notes = "" +tools = ["image_edit"] +evidence = ["crates/edit/src/tests.rs::image_arrange_stacking_order_and_remove_crop"] +notes = "Image stacking order in content streams: Bring to Front, Send to Back, Bring Forward, Send Backward with undo/redo and PDF export persistence. Image-level crop and 8-point handle transforms. Still missing: arbitrary vector paths, inline images, and multi-object grouping." [[feature]] id = "edit.align-distribute-objects"