diff --git a/crates/engine/src/text_fonts.rs b/crates/engine/src/text_fonts.rs index 7c3fc3211e..ca77b0d8af 100644 --- a/crates/engine/src/text_fonts.rs +++ b/crates/engine/src/text_fonts.rs @@ -88,4 +88,3 @@ mod tests { assert!(!dirs.is_empty()); } } - diff --git a/crates/ui-egui/src/canvas.rs b/crates/ui-egui/src/canvas.rs index aacc091bff..7623913f44 100644 --- a/crates/ui-egui/src/canvas.rs +++ b/crates/ui-egui/src/canvas.rs @@ -3242,7 +3242,9 @@ pub fn document_area(app: &mut PdfCraftApp, index: usize, ui: &mut egui::Ui) { } return; } - if tool == QuickTool::EditText && let Some(sel) = view.image_selection.clone() { + if tool == QuickTool::EditText + && let Some(sel) = view.image_selection.clone() + { crate::edit_text_ui::image_context_menu(ui, view, doc, sel.page, sel.index, can_paste_image, &mut image_action); return; } @@ -3612,7 +3614,9 @@ pub fn document_area(app: &mut PdfCraftApp, index: usize, ui: &mut egui::Ui) { if let Some(sel) = app.views[index].image_selection.clone() { app.copy_page_image(sel.page, sel.index); } else if let Some(text) = app.views[index].selected_text() { - if let Some(id) = app.views.get(index).map(|v| v.id) && app.may_copy(id) { + if let Some(id) = app.views.get(index).map(|v| v.id) + && app.may_copy(id) + { ui.ctx().copy_text(text); } } else if let Some((page, at)) = app.views[index].comments.context_at @@ -3644,13 +3648,8 @@ pub fn document_area(app: &mut PdfCraftApp, index: usize, ui: &mut egui::Ui) { app.quick_tool = QuickTool::MarqueeZoom; } Some(PageMenuAction::AddComment(page, at)) => { - app.views[index].comments.composer = Some(crate::comments::Composer { - page, - at, - kind: crate::comments::ComposerKind::Note, - text: String::new(), - focus: true, - }); + app.views[index].comments.composer = + Some(crate::comments::Composer { page, at, kind: crate::comments::ComposerKind::Note, text: String::new(), focus: true }); } Some(PageMenuAction::AddBookmark(_page)) => { app.bookmark_action(crate::panels::BmAction::New); diff --git a/crates/ui-egui/src/content_ui.rs b/crates/ui-egui/src/content_ui.rs index 70c03d0a1a..c9d0206413 100644 --- a/crates/ui-egui/src/content_ui.rs +++ b/crates/ui-egui/src/content_ui.rs @@ -552,24 +552,18 @@ fn finish(cv: &mut ContentView, d: TextDraft, added: &[Added]) -> Option { pub(crate) fn format_panel(ui: &mut egui::Ui, t: &Tokens, style: &AddedText) -> Option { let mut s = style.clone(); widgets::section_title(ui, tl!("FORMAT TEXT")); - egui::ComboBox::from_id_salt("font-family") - .selected_text(s.family.label()) - .width(ui.available_width().max(180.0)) - .show_ui(ui, |ui| { - ui.label(egui::RichText::new(tl!("Standard fonts")).weak().small()); - for f in [FontFamily::Helvetica, FontFamily::Times, FontFamily::Courier] { - ui.selectable_value(&mut s.family, f, f.label()); + egui::ComboBox::from_id_salt("font-family").selected_text(s.family.label()).width(ui.available_width().max(180.0)).show_ui(ui, |ui| { + ui.label(egui::RichText::new(tl!("Standard fonts")).weak().small()); + for f in [FontFamily::Helvetica, FontFamily::Times, FontFamily::Courier] { + ui.selectable_value(&mut s.family, f, f.label()); + } + }); + ui.horizontal(|ui| { + egui::ComboBox::from_id_salt("font-size").selected_text(format!("{:.1}", s.size)).width(55.0).show_ui(ui, |ui| { + for size in [6.0, 8.0, 9.0, 10.0, 10.5, 11.0, 12.0, 14.0, 16.0, 18.0, 20.0, 24.0, 28.0, 36.0, 48.0, 72.0] { + ui.selectable_value(&mut s.size, size, format!("{size}")); } }); - ui.horizontal(|ui| { - egui::ComboBox::from_id_salt("font-size") - .selected_text(format!("{:.1}", s.size)) - .width(55.0) - .show_ui(ui, |ui| { - for size in [6.0, 8.0, 9.0, 10.0, 10.5, 11.0, 12.0, 14.0, 16.0, 18.0, 20.0, 24.0, 28.0, 36.0, 48.0, 72.0] { - ui.selectable_value(&mut s.size, size, format!("{size}")); - } - }); let (color_rect, color_resp) = ui.allocate_exact_size(egui::vec2(20.0, 20.0), egui::Sense::click()); let color_val = crate::comments::color32(s.color); ui.painter().rect_filled(color_rect, t.radius, color_val); @@ -759,11 +753,7 @@ impl crate::PdfCraftApp { pub(crate) fn cut_page_image(&mut self, view_idx: usize, page: usize, index: usize) { self.copy_page_image(page, index); if let Some(view) = self.views.get_mut(view_idx) { - view.pending_edit = Some(pdfcraft_engine::Edit::EditPageImage { - page, - index, - change: pdfcraft_engine::ImageEdit::Delete, - }); + view.pending_edit = Some(pdfcraft_engine::Edit::EditPageImage { page, index, change: pdfcraft_engine::ImageEdit::Delete }); view.image_selection = None; } } @@ -783,7 +773,9 @@ impl crate::PdfCraftApp { /// Paste an image from the clipboard onto `page`. pub fn paste_image(&mut self, page: usize, rect: Option<[f64; 4]>) -> bool { - let Some((i, id)) = self.active_ids() else { return false; }; + let Some((i, id)) = self.active_ids() else { + return false; + }; if let Some(doc) = self.session.get(id) && !doc.allows_modification() { @@ -808,9 +800,10 @@ impl crate::PdfCraftApp { let image_data: Option<(String, Vec)> = if has_system_cb { match os_image { Some((width, height, bytes)) => { - let matches_internal = self.last_copied_image.as_ref().is_some_and(|(w, h, rgba)| { - *w as usize == width && *h as usize == height && rgba.as_slice() == bytes.as_slice() - }); + let matches_internal = self + .last_copied_image + .as_ref() + .is_some_and(|(w, h, rgba)| *w as usize == width && *h as usize == height && rgba.as_slice() == bytes.as_slice()); if matches_internal && let Some((name, file_bytes)) = self.last_copied_file.clone() { Some((name, file_bytes)) } else if let Ok(png_bytes) = crate::create_ui::png_from_rgba(width, height, &bytes) { @@ -857,21 +850,10 @@ impl crate::PdfCraftApp { }; let before = self.session.get(id).map_or(0, |d| d.page_images(page).len()); - if self.apply_edit(pdfcraft_engine::Edit::AddImage { - page, - rect: target_rect, - name, - bytes: std::sync::Arc::new(bytes), - }) { + if self.apply_edit(pdfcraft_engine::Edit::AddImage { page, rect: target_rect, name, bytes: std::sync::Arc::new(bytes) }) { if let Some(v) = self.views.get_mut(i) { v.current = page; - v.image_selection = Some(crate::edit_text_ui::ImageSelection { - page, - index: before, - crop_mode: false, - crop_rect: None, - drag: None, - }); + v.image_selection = Some(crate::edit_text_ui::ImageSelection { page, index: before, crop_mode: false, crop_rect: None, drag: None }); } self.quick_tool = crate::QuickTool::EditText; self.notify_tr("Image pasted"); diff --git a/crates/ui-egui/src/edit_text_ui.rs b/crates/ui-egui/src/edit_text_ui.rs index 7af7b1091e..b2563fb24e 100644 --- a/crates/ui-egui/src/edit_text_ui.rs +++ b/crates/ui-egui/src/edit_text_ui.rs @@ -244,62 +244,206 @@ pub fn toggle_numbered_list(text: &mut String) -> bool { pub fn char_to_superscript(c: char) -> char { match c { - '0' => '⁰', '1' => '¹', '2' => '²', '3' => '³', '4' => '⁴', - '5' => '⁵', '6' => '⁶', '7' => '⁷', '8' => '⁸', '9' => '⁹', - '+' => '⁺', '-' | '−' => '⁻', '=' => '⁼', '(' => '⁽', ')' => '⁾', - 'a' => 'ᵃ', 'b' => 'ᵇ', 'c' => 'ᶜ', 'd' => 'ᵈ', 'e' => 'ᵉ', - 'f' => 'ᶠ', 'g' => 'ᵍ', 'h' => 'ʰ', 'i' => 'ⁱ', 'j' => 'ʲ', - 'k' => 'ᵏ', 'l' => 'ˡ', 'm' => 'ᵐ', 'n' => 'ⁿ', 'o' => 'ᵒ', - 'p' => 'ᵖ', 'r' => 'ʳ', 's' => 'ˢ', 't' => 'ᵗ', 'u' => 'ᵘ', - 'v' => 'ᵛ', 'w' => 'ʷ', 'x' => 'ˣ', 'y' => 'ʸ', 'z' => 'ᶻ', - 'A' => 'ᴬ', 'B' => 'ᴮ', 'D' => 'ᴰ', 'E' => 'ᴱ', 'G' => 'ᴳ', - 'H' => 'ᴴ', 'I' => 'ᴵ', 'J' => 'ᴶ', 'K' => 'ᴷ', 'L' => 'ᴸ', - 'M' => 'ᴹ', 'N' => 'ᴺ', 'O' => 'ᴼ', 'P' => 'ᴾ', 'R' => 'ᴿ', - 'T' => 'ᵀ', 'U' => 'ᵁ', 'V' => 'ⱽ', 'W' => 'ᵂ', + '0' => '⁰', + '1' => '¹', + '2' => '²', + '3' => '³', + '4' => '⁴', + '5' => '⁵', + '6' => '⁶', + '7' => '⁷', + '8' => '⁸', + '9' => '⁹', + '+' => '⁺', + '-' | '−' => '⁻', + '=' => '⁼', + '(' => '⁽', + ')' => '⁾', + 'a' => 'ᵃ', + 'b' => 'ᵇ', + 'c' => 'ᶜ', + 'd' => 'ᵈ', + 'e' => 'ᵉ', + 'f' => 'ᶠ', + 'g' => 'ᵍ', + 'h' => 'ʰ', + 'i' => 'ⁱ', + 'j' => 'ʲ', + 'k' => 'ᵏ', + 'l' => 'ˡ', + 'm' => 'ᵐ', + 'n' => 'ⁿ', + 'o' => 'ᵒ', + 'p' => 'ᵖ', + 'r' => 'ʳ', + 's' => 'ˢ', + 't' => 'ᵗ', + 'u' => 'ᵘ', + 'v' => 'ᵛ', + 'w' => 'ʷ', + 'x' => 'ˣ', + 'y' => 'ʸ', + 'z' => 'ᶻ', + 'A' => 'ᴬ', + 'B' => 'ᴮ', + 'D' => 'ᴰ', + 'E' => 'ᴱ', + 'G' => 'ᴳ', + 'H' => 'ᴴ', + 'I' => 'ᴵ', + 'J' => 'ᴶ', + 'K' => 'ᴷ', + 'L' => 'ᴸ', + 'M' => 'ᴹ', + 'N' => 'ᴺ', + 'O' => 'ᴼ', + 'P' => 'ᴾ', + 'R' => 'ᴿ', + 'T' => 'ᵀ', + 'U' => 'ᵁ', + 'V' => 'ⱽ', + 'W' => 'ᵂ', other => other, } } pub fn char_from_superscript(c: char) -> char { match c { - '⁰' => '0', '¹' => '1', '²' => '2', '³' => '3', '⁴' => '4', - '⁵' => '5', '⁶' => '6', '⁷' => '7', '⁸' => '8', '⁹' => '9', - '⁺' => '+', '⁻' => '-', '⁼' => '=', '⁽' => '(', '⁾' => ')', - 'ᵃ' => 'a', 'ᵇ' => 'b', 'ᶜ' => 'c', 'ᵈ' => 'd', 'ᵉ' => 'e', - 'ᶠ' => 'f', 'ᵍ' => 'g', 'ʰ' => 'h', 'ⁱ' => 'i', 'ʲ' => 'j', - 'ᵏ' => 'k', 'ˡ' => 'l', 'ᵐ' => 'm', 'ⁿ' => 'n', 'ᵒ' => 'o', - 'ᵖ' => 'p', 'ʳ' => 'r', 'ˢ' => 's', 'ᵗ' => 't', 'ᵘ' => 'u', - 'ᵛ' => 'v', 'ʷ' => 'w', 'ˣ' => 'x', 'ʸ' => 'y', 'ᶻ' => 'z', - 'ᴬ' => 'A', 'ᴮ' => 'B', 'ᴰ' => 'D', 'ᴱ' => 'E', 'ᴳ' => 'G', - 'ᴴ' => 'H', 'ᴵ' => 'I', 'ᴶ' => 'J', 'ᴷ' => 'K', 'ᴸ' => 'L', - 'ᴹ' => 'M', 'ᴺ' => 'N', 'ᴼ' => 'O', 'ᴾ' => 'P', 'ᴿ' => 'R', - 'ᵀ' => 'T', 'ᵁ' => 'U', 'ⱽ' => 'V', 'ᵂ' => 'W', + '⁰' => '0', + '¹' => '1', + '²' => '2', + '³' => '3', + '⁴' => '4', + '⁵' => '5', + '⁶' => '6', + '⁷' => '7', + '⁸' => '8', + '⁹' => '9', + '⁺' => '+', + '⁻' => '-', + '⁼' => '=', + '⁽' => '(', + '⁾' => ')', + 'ᵃ' => 'a', + 'ᵇ' => 'b', + 'ᶜ' => 'c', + 'ᵈ' => 'd', + 'ᵉ' => 'e', + 'ᶠ' => 'f', + 'ᵍ' => 'g', + 'ʰ' => 'h', + 'ⁱ' => 'i', + 'ʲ' => 'j', + 'ᵏ' => 'k', + 'ˡ' => 'l', + 'ᵐ' => 'm', + 'ⁿ' => 'n', + 'ᵒ' => 'o', + 'ᵖ' => 'p', + 'ʳ' => 'r', + 'ˢ' => 's', + 'ᵗ' => 't', + 'ᵘ' => 'u', + 'ᵛ' => 'v', + 'ʷ' => 'w', + 'ˣ' => 'x', + 'ʸ' => 'y', + 'ᶻ' => 'z', + 'ᴬ' => 'A', + 'ᴮ' => 'B', + 'ᴰ' => 'D', + 'ᴱ' => 'E', + 'ᴳ' => 'G', + 'ᴴ' => 'H', + 'ᴵ' => 'I', + 'ᴶ' => 'J', + 'ᴷ' => 'K', + 'ᴸ' => 'L', + 'ᴹ' => 'M', + 'ᴺ' => 'N', + 'ᴼ' => 'O', + 'ᴾ' => 'P', + 'ᴿ' => 'R', + 'ᵀ' => 'T', + 'ᵁ' => 'U', + 'ⱽ' => 'V', + 'ᵂ' => 'W', other => other, } } pub fn char_to_subscript(c: char) -> char { match c { - '0' => '₀', '1' => '₁', '2' => '₂', '3' => '₃', '4' => '₄', - '5' => '₅', '6' => '₆', '7' => '₇', '8' => '₈', '9' => '₉', - '+' => '₊', '-' | '−' => '₋', '=' => '₌', '(' => '₍', ')' => '₎', - 'a' => 'ₐ', 'e' => 'ₑ', 'h' => 'ₕ', 'i' => 'ᵢ', 'j' => 'ⱼ', - 'k' => 'ₖ', 'l' => 'ₗ', 'm' => 'ₘ', 'n' => 'ₙ', 'o' => 'ₒ', - 'p' => 'ₚ', 'r' => 'ᵣ', 's' => 'ₛ', 't' => 'ₜ', 'u' => 'ᵤ', - 'v' => 'ᵥ', 'x' => 'ₓ', + '0' => '₀', + '1' => '₁', + '2' => '₂', + '3' => '₃', + '4' => '₄', + '5' => '₅', + '6' => '₆', + '7' => '₇', + '8' => '₈', + '9' => '₉', + '+' => '₊', + '-' | '−' => '₋', + '=' => '₌', + '(' => '₍', + ')' => '₎', + 'a' => 'ₐ', + 'e' => 'ₑ', + 'h' => 'ₕ', + 'i' => 'ᵢ', + 'j' => 'ⱼ', + 'k' => 'ₖ', + 'l' => 'ₗ', + 'm' => 'ₘ', + 'n' => 'ₙ', + 'o' => 'ₒ', + 'p' => 'ₚ', + 'r' => 'ᵣ', + 's' => 'ₛ', + 't' => 'ₜ', + 'u' => 'ᵤ', + 'v' => 'ᵥ', + 'x' => 'ₓ', other => other, } } pub fn char_from_subscript(c: char) -> char { match c { - '₀' => '0', '₁' => '1', '₂' => '2', '₃' => '3', '₄' => '4', - '₅' => '5', '₆' => '6', '₇' => '7', '₈' => '8', '₉' => '9', - '₊' => '+', '₋' => '-', '₌' => '=', '₍' => '(', '₎' => ')', - 'ₐ' => 'a', 'ₑ' => 'e', 'ₕ' => 'h', 'ᵢ' => 'i', 'ⱼ' => 'j', - 'ₖ' => 'k', 'ₗ' => 'l', 'ₘ' => 'm', 'ₙ' => 'n', 'ₒ' => 'o', - 'ₚ' => 'p', 'ᵣ' => 'r', 'ₛ' => 's', 'ₜ' => 't', 'ᵤ' => 'u', - 'ᵥ' => 'v', 'ₓ' => 'x', + '₀' => '0', + '₁' => '1', + '₂' => '2', + '₃' => '3', + '₄' => '4', + '₅' => '5', + '₆' => '6', + '₇' => '7', + '₈' => '8', + '₉' => '9', + '₊' => '+', + '₋' => '-', + '₌' => '=', + '₍' => '(', + '₎' => ')', + 'ₐ' => 'a', + 'ₑ' => 'e', + 'ₕ' => 'h', + 'ᵢ' => 'i', + 'ⱼ' => 'j', + 'ₖ' => 'k', + 'ₗ' => 'l', + 'ₘ' => 'm', + 'ₙ' => 'n', + 'ₒ' => 'o', + 'ₚ' => 'p', + 'ᵣ' => 'r', + 'ₛ' => 's', + 'ₜ' => 't', + 'ᵤ' => 'u', + 'ᵥ' => 'v', + 'ₓ' => 'x', other => other, } } @@ -317,22 +461,15 @@ fn snap_char_boundaries(s: &str, start: usize, end: usize) -> (usize, usize) { } pub fn toggle_superscript(ed: &mut LineEditor) -> bool { - let (s_pos, e_pos) = if let Some(r) = &ed.selection { - (r.start.min(ed.text.len()), r.end.min(ed.text.len())) - } else { - (0, ed.text.len()) - }; + let (s_pos, e_pos) = if let Some(r) = &ed.selection { (r.start.min(ed.text.len()), r.end.min(ed.text.len())) } else { (0, ed.text.len()) }; let (start, end) = snap_char_boundaries(&ed.text, s_pos, e_pos); if start >= end { return false; } let target = &ed.text[start..end]; let all_sup = target.chars().all(|c| char_from_superscript(c) != c); - let converted: String = if all_sup { - target.chars().map(char_from_superscript).collect() - } else { - target.chars().map(char_to_superscript).collect() - }; + let converted: String = + if all_sup { target.chars().map(char_from_superscript).collect() } else { target.chars().map(char_to_superscript).collect() }; if converted != target { let conv_len = converted.len(); ed.text.replace_range(start..end, &converted); @@ -346,22 +483,14 @@ pub fn toggle_superscript(ed: &mut LineEditor) -> bool { } pub fn toggle_subscript(ed: &mut LineEditor) -> bool { - let (s_pos, e_pos) = if let Some(r) = &ed.selection { - (r.start.min(ed.text.len()), r.end.min(ed.text.len())) - } else { - (0, ed.text.len()) - }; + let (s_pos, e_pos) = if let Some(r) = &ed.selection { (r.start.min(ed.text.len()), r.end.min(ed.text.len())) } else { (0, ed.text.len()) }; let (start, end) = snap_char_boundaries(&ed.text, s_pos, e_pos); if start >= end { return false; } let target = &ed.text[start..end]; let all_sub = target.chars().all(|c| char_from_subscript(c) != c); - let converted: String = if all_sub { - target.chars().map(char_from_subscript).collect() - } else { - target.chars().map(char_to_subscript).collect() - }; + let converted: String = if all_sub { target.chars().map(char_from_subscript).collect() } else { target.chars().map(char_to_subscript).collect() }; if converted != target { let conv_len = converted.len(); ed.text.replace_range(start..end, &converted); @@ -842,10 +971,18 @@ pub(crate) fn image_input( painter.rect_filled(Rect::from_min_max(Pos2::new(b.left(), active_crop.bottom()), b.max), CornerRadius::ZERO, shade_color); } if active_crop.left() > b.left() { - painter.rect_filled(Rect::from_min_max(Pos2::new(b.left(), active_crop.top()), Pos2::new(active_crop.left(), active_crop.bottom())), CornerRadius::ZERO, shade_color); + painter.rect_filled( + Rect::from_min_max(Pos2::new(b.left(), active_crop.top()), Pos2::new(active_crop.left(), active_crop.bottom())), + CornerRadius::ZERO, + shade_color, + ); } if active_crop.right() < b.right() { - painter.rect_filled(Rect::from_min_max(Pos2::new(active_crop.right(), active_crop.top()), Pos2::new(b.right(), active_crop.bottom())), CornerRadius::ZERO, shade_color); + painter.rect_filled( + Rect::from_min_max(Pos2::new(active_crop.right(), active_crop.top()), Pos2::new(b.right(), active_crop.bottom())), + CornerRadius::ZERO, + shade_color, + ); } painter.rect_stroke(active_crop, CornerRadius::ZERO, Stroke::new(1.5, ACCENT), egui::StrokeKind::Outside); @@ -853,10 +990,14 @@ pub(crate) fn image_input( let x2 = active_crop.left() + active_crop.width() * 2.0 / 3.0; let y1 = active_crop.top() + active_crop.height() / 3.0; let y2 = active_crop.top() + active_crop.height() * 2.0 / 3.0; - painter.line_segment([Pos2::new(x1, active_crop.top()), Pos2::new(x1, active_crop.bottom())], Stroke::new(0.75, ACCENT.gamma_multiply(0.5))); - painter.line_segment([Pos2::new(x2, active_crop.top()), Pos2::new(x2, active_crop.bottom())], Stroke::new(0.75, ACCENT.gamma_multiply(0.5))); - painter.line_segment([Pos2::new(active_crop.left(), y1), Pos2::new(active_crop.right(), y1)], Stroke::new(0.75, ACCENT.gamma_multiply(0.5))); - painter.line_segment([Pos2::new(active_crop.left(), y2), Pos2::new(active_crop.right(), y2)], Stroke::new(0.75, ACCENT.gamma_multiply(0.5))); + painter + .line_segment([Pos2::new(x1, active_crop.top()), Pos2::new(x1, active_crop.bottom())], Stroke::new(0.75, ACCENT.gamma_multiply(0.5))); + painter + .line_segment([Pos2::new(x2, active_crop.top()), Pos2::new(x2, active_crop.bottom())], Stroke::new(0.75, ACCENT.gamma_multiply(0.5))); + painter + .line_segment([Pos2::new(active_crop.left(), y1), Pos2::new(active_crop.right(), y1)], Stroke::new(0.75, ACCENT.gamma_multiply(0.5))); + painter + .line_segment([Pos2::new(active_crop.left(), y2), Pos2::new(active_crop.right(), y2)], Stroke::new(0.75, ACCENT.gamma_multiply(0.5))); let crop_handles = [ ImageHandle::TopLeft, @@ -875,7 +1016,13 @@ pub(crate) fn image_input( ImageHandle::LeftCenter | ImageHandle::RightCenter => egui::vec2(6.0, 16.0), _ => egui::vec2(10.0, 10.0), }; - painter.rect(Rect::from_center_size(c, sz), CornerRadius::same(1), Color32::WHITE, Stroke::new(1.5, ACCENT), egui::StrokeKind::Middle); + painter.rect( + Rect::from_center_size(c, sz), + CornerRadius::same(1), + Color32::WHITE, + Stroke::new(1.5, ACCENT), + egui::StrokeKind::Middle, + ); } if allow_interaction && let Some(p) = hover_pos { @@ -897,11 +1044,7 @@ pub(crate) fn image_input( change: pdfcraft_engine::ImageEdit::Crop(user_box(xf, info, page, active_crop)), }); } else if images.get(i).is_some_and(|im| im.visible_rect.is_some() && im.visible_rect != Some(im.rect)) { - view.pending_edit = Some(Edit::EditPageImage { - page, - index: i, - change: pdfcraft_engine::ImageEdit::RemoveCrop, - }); + view.pending_edit = Some(Edit::EditPageImage { page, index: i, change: pdfcraft_engine::ImageEdit::RemoveCrop }); } if let Some(s) = view.image_selection.as_mut() { s.crop_mode = false; @@ -931,7 +1074,10 @@ pub(crate) fn image_input( } let origin = ui.input(|i| i.pointer.press_origin()); - if allow_interaction && resp.drag_started() && let Some(o) = origin { + if allow_interaction + && resp.drag_started() + && let Some(o) = origin + { if is_crop { let active_crop = view.image_selection.as_ref().and_then(|s| s.crop_rect).unwrap_or(b); let crop_handles = [ @@ -1167,14 +1313,13 @@ pub(crate) fn image_input( || ui.ctx().is_pointer_over_egui() || ui.ctx().egui_wants_pointer_input(); if (resp.secondary_clicked() || resp.clicked()) && !over_popup { - if let Some(s) = view.image_selection.as_mut() && s.crop_mode { + if let Some(s) = view.image_selection.as_mut() + && s.crop_mode + { let img_box = boxes.get(s.index).copied(); if let Some(crop) = s.crop_rect.filter(|c| img_box.is_some_and(|b| *c != b)) { - view.pending_edit = Some(Edit::EditPageImage { - page, - index: s.index, - change: pdfcraft_engine::ImageEdit::Crop(user_box(xf, info, page, crop)), - }); + view.pending_edit = + Some(Edit::EditPageImage { page, index: s.index, change: pdfcraft_engine::ImageEdit::Crop(user_box(xf, info, page, crop)) }); } } view.image_selection = None; @@ -1278,44 +1423,28 @@ pub(crate) fn image_context_menu( ui.menu_button(tl!("Arrange image"), |ui| { let total = images.len(); if ui.button(tl!("Bring to front")).clicked() { - view.pending_edit = Some(Edit::EditPageImage { - page, - index: hit, - change: E::Arrange(pdfcraft_engine::ArrangeOrder::BringToFront), - }); + view.pending_edit = Some(Edit::EditPageImage { page, index: hit, change: E::Arrange(pdfcraft_engine::ArrangeOrder::BringToFront) }); if let Some(s) = view.image_selection.as_mut() { s.index = total.saturating_sub(1); } ui.close(); } if ui.button(tl!("Send to back")).clicked() { - view.pending_edit = Some(Edit::EditPageImage { - page, - index: hit, - change: E::Arrange(pdfcraft_engine::ArrangeOrder::SendToBack), - }); + view.pending_edit = Some(Edit::EditPageImage { page, index: hit, change: E::Arrange(pdfcraft_engine::ArrangeOrder::SendToBack) }); if let Some(s) = view.image_selection.as_mut() { s.index = 0; } ui.close(); } if ui.button(tl!("Bring forward")).clicked() { - view.pending_edit = Some(Edit::EditPageImage { - page, - index: hit, - change: E::Arrange(pdfcraft_engine::ArrangeOrder::BringForward), - }); + view.pending_edit = Some(Edit::EditPageImage { page, index: hit, change: E::Arrange(pdfcraft_engine::ArrangeOrder::BringForward) }); if let Some(s) = view.image_selection.as_mut() { s.index = (hit + 1).min(total.saturating_sub(1)); } ui.close(); } if ui.button(tl!("Send backward")).clicked() { - view.pending_edit = Some(Edit::EditPageImage { - page, - index: hit, - change: E::Arrange(pdfcraft_engine::ArrangeOrder::SendBackward), - }); + view.pending_edit = Some(Edit::EditPageImage { page, index: hit, change: E::Arrange(pdfcraft_engine::ArrangeOrder::SendBackward) }); if let Some(s) = view.image_selection.as_mut() { s.index = hit.saturating_sub(1); } diff --git a/crates/ui-egui/src/files.rs b/crates/ui-egui/src/files.rs index a5dbbabd6a..9ffb567fd8 100644 --- a/crates/ui-egui/src/files.rs +++ b/crates/ui-egui/src/files.rs @@ -466,9 +466,8 @@ impl PdfCraftApp { if self.apply_edit(Edit::RegisterTextFont { page, bytes: Arc::new(bytes.clone()) }) && let Some((index, id)) = self.active_ids() { - let resource = self.session.get(id).and_then(|doc| { - doc.text_editor_fonts(page).into_iter().find(|f| f.bytes == bytes).map(|f| f.resource) - }); + let resource = + self.session.get(id).and_then(|doc| doc.text_editor_fonts(page).into_iter().find(|f| f.bytes == bytes).map(|f| f.resource)); if let Some(resource) = resource && let Some(ed) = self.views[index].line_editor.as_mut() { diff --git a/crates/ui-egui/src/panels.rs b/crates/ui-egui/src/panels.rs index 6f9758ac9a..7cd417d863 100644 --- a/crates/ui-egui/src/panels.rs +++ b/crates/ui-egui/src/panels.rs @@ -359,10 +359,9 @@ fn format_section(app: &mut PdfCraftApp, ui: &mut egui::Ui, t: &Tokens) { }; crate::widgets::section_title(ui, tl!("FORMAT TEXT")); - egui::ComboBox::from_id_salt("text-font-dropdown") - .selected_text(current_font_label) - .width(ui.available_width().max(180.0)) - .show_ui(ui, |ui| { + egui::ComboBox::from_id_salt("text-font-dropdown").selected_text(current_font_label).width(ui.available_width().max(180.0)).show_ui( + ui, + |ui| { if ui.selectable_label(ed.font_resource.is_none(), tl!("Keep source fonts")).clicked() { ed.font_resource = None; changed = true; @@ -397,9 +396,8 @@ fn format_section(app: &mut PdfCraftApp, ui: &mut egui::Ui, t: &Tokens) { ui.label(egui::RichText::new(tl!("No installed fonts found.")).weak().small()); } else { for font in &installed { - let is_current = ed.font_resource.as_ref().is_some_and(|r| { - font_choices.iter().any(|f| &f.resource == r && f.face == font.face) - }); + 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() && let Ok(bytes) = std::fs::read(&font.path) { @@ -424,18 +422,16 @@ fn format_section(app: &mut PdfCraftApp, ui: &mut egui::Ui, t: &Tokens) { if ui.button(tl!("Load font from file…")).clicked() { app.pick_files(crate::files::FilePurpose::TextFont { page: ed.page }, false); } - }); + }, + ); ui.horizontal(|ui| { // Font size ComboBox - egui::ComboBox::from_id_salt("font-size") - .selected_text(format!("{:.1}", ed.look.size)) - .width(55.0) - .show_ui(ui, |ui| { - for size in [6.0, 8.0, 9.0, 10.0, 10.5, 11.0, 12.0, 14.0, 16.0, 18.0, 20.0, 24.0, 28.0, 36.0, 48.0, 72.0] { - changed |= ui.selectable_value(&mut ed.look.size, size, format!("{size}")).changed(); - } - }); + egui::ComboBox::from_id_salt("font-size").selected_text(format!("{:.1}", ed.look.size)).width(55.0).show_ui(ui, |ui| { + for size in [6.0, 8.0, 9.0, 10.0, 10.5, 11.0, 12.0, 14.0, 16.0, 18.0, 20.0, 24.0, 28.0, 36.0, 48.0, 72.0] { + changed |= ui.selectable_value(&mut ed.look.size, size, format!("{size}")).changed(); + } + }); // Color swatch square let (color_rect, color_resp) = ui.allocate_exact_size(egui::vec2(20.0, 20.0), egui::Sense::click()); let color_val = crate::comments::color32(ed.look.color); diff --git a/crates/ui-egui/tests/editing.rs b/crates/ui-egui/tests/editing.rs index 9055414169..05357891ea 100644 --- a/crates/ui-egui/tests/editing.rs +++ b/crates/ui-egui/tests/editing.rs @@ -2639,15 +2639,8 @@ fn default_page_context_menu_when_not_in_edit_mode() { h.get_by_label("Hand Tool"); h.get_by_label("Marquee Zoom"); - for item in [ - "Add bookmark", - "Take a snapshot", - "Edit this PDF", - "Delete page", - "Export this PDF", - "Find text or tools", - "Document properties…", - ] { + for item in ["Add bookmark", "Take a snapshot", "Edit this PDF", "Delete page", "Export this PDF", "Find text or tools", "Document properties…"] + { h.get_by_label_contains(item); } h.get_by_label("Rotate view clockwise"); @@ -2666,7 +2659,9 @@ fn default_page_context_menu_when_not_in_edit_mode() { #[test] fn image_edge_handle_stretch_and_crop_mode() { let mut png = Vec::new(); - image::RgbImage::from_pixel(100, 100, image::Rgb([100, 150, 200])).write_to(&mut std::io::Cursor::new(&mut png), image::ImageFormat::Png).unwrap(); + image::RgbImage::from_pixel(100, 100, image::Rgb([100, 150, 200])) + .write_to(&mut std::io::Cursor::new(&mut png), image::ImageFormat::Png) + .unwrap(); let mut h = Harness::builder().with_size(egui::vec2(1400.0, 900.0)).build_eframe(move |_cc| { let mut app = PdfCraftApp::new(); app.set_option("language", "en").unwrap(); @@ -2738,13 +2733,7 @@ fn tiny_image_crop_handle_drag_does_not_panic() { // Enter crop mode on image 0 let view = &mut h.state_mut().views[0]; - view.image_selection = Some(pdfcraft_ui_egui::ImageSelection { - page: 0, - index: 0, - drag: None, - crop_mode: true, - crop_rect: None, - }); + view.image_selection = Some(pdfcraft_ui_egui::ImageSelection { page: 0, index: 0, drag: None, crop_mode: true, crop_rect: None }); h.run_steps(1); // Simulate drag on TopLeft crop handle with an initial_rect of 5.0 x 5.0 @@ -4420,9 +4409,7 @@ fn private_new_chinese_keyboard_input_preserves_font_layout_and_saved_pixels() { #[test] fn image_copy_cut_paste_keyboard_and_context_menu() { let mut png = Vec::new(); - image::RgbImage::from_pixel(60, 40, image::Rgb([180, 50, 50])) - .write_to(&mut std::io::Cursor::new(&mut png), image::ImageFormat::Png) - .unwrap(); + image::RgbImage::from_pixel(60, 40, image::Rgb([180, 50, 50])).write_to(&mut std::io::Cursor::new(&mut png), image::ImageFormat::Png).unwrap(); let mut h = Harness::builder().with_size(egui::vec2(1400.0, 900.0)).build_eframe(move |_cc| { let mut app = PdfCraftApp::new(); app.set_option("language", "en").unwrap(); @@ -4502,4 +4489,3 @@ fn stale_clipboard_plain_text_does_not_paste_image() { // paste_image should fail and return false without pasting assert!(!h.state_mut().paste_image(0, None), "must not paste stale cached image"); } -