chore: format remaining workspace files

This commit is contained in:
Combiler01
2026-10-15 01:54:05 +05:30
parent daa6286466
commit dd5b7e7735
7 changed files with 275 additions and 185 deletions
-1
View File
@@ -88,4 +88,3 @@ mod tests {
assert!(!dirs.is_empty());
}
}
+8 -9
View File
@@ -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);
+20 -38
View File
@@ -552,24 +552,18 @@ fn finish(cv: &mut ContentView, d: TextDraft, added: &[Added]) -> Option<Edit> {
pub(crate) fn format_panel(ui: &mut egui::Ui, t: &Tokens, style: &AddedText) -> Option<AddedText> {
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<u8>)> = 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");
+226 -97
View File
@@ -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);
}
+2 -3
View File
@@ -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()
{
+12 -16
View File
@@ -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);
+7 -21
View File
@@ -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");
}