fix(ui): adapt custom controls to egui 0.37 API and deprecations

This commit is contained in:
Combiler01
2026-10-26 10:40:41 +05:30
parent 3dfcff3884
commit bf2c246a68
8 changed files with 42 additions and 40 deletions
+23 -20
View File
@@ -3460,7 +3460,7 @@ pub fn document_area(app: &mut PdfCraftApp, index: usize, ui: &mut egui::Ui) {
let show_secured_notice = app.show_secured_notice;
// Asking means opening the system clipboard (and decoding any image on it), so it's asked
// once when a right-click opens a menu, not on every frame.
let can_paste_key = egui::Id::new("can-paste-image");
let can_paste_key = egui::Id::unique("can-paste-image");
let can_paste_image = if ui.input(|i| i.pointer.secondary_pressed()) {
let can = app.can_paste_image();
ui.data_mut(|d| d.insert_temp(can_paste_key, can));
@@ -5539,29 +5539,32 @@ fn selection_actions(
let x = ideal_x.clamp(viewport.left() + 8.0, max_x);
let y = if rect.bottom() + 48.0 < viewport.bottom() { rect.bottom() + 6.0 } else { (rect.top() - 44.0).max(viewport.top() + 6.0) };
let mut chosen = None;
egui::Area::new(egui::Id::new(("text-selection-actions", view.id.0))).order(egui::Order::Foreground).fixed_pos(pos2(x, y)).show(ui.ctx(), |ui| {
egui::Frame::popup(ui.style()).corner_radius(CornerRadius::same(12)).show(ui, |ui| {
ui.spacing_mut().item_spacing.x = 2.0;
ui.horizontal(|ui| {
ui.add_enabled_ui(can_comment, |ui| {
for (icon, tooltip, action) in [
("message-square-plus", tl!("Add comment"), SelectionAction::Note),
("highlighter", tl!("Highlight"), SelectionAction::Markup(comments::CommentTool::Highlight)),
("underline", tl!("Underline"), SelectionAction::Markup(comments::CommentTool::Underline)),
("strikethrough", tl!("Strikethrough"), SelectionAction::Markup(comments::CommentTool::StrikeOut)),
("replace", tl!("Replace text"), SelectionAction::Replace),
] {
if icons::button(ui, icon, 26.0, false, tooltip).clicked() {
chosen = Some(action);
egui::Area::new(egui::Id::unique(("text-selection-actions", view.id.0))).order(egui::Order::Foreground).fixed_pos(pos2(x, y)).show(
ui.ctx(),
|ui| {
egui::Frame::popup(ui.style()).corner_radius(CornerRadius::same(12)).show(ui, |ui| {
ui.spacing_mut().item_spacing.x = 2.0;
ui.horizontal(|ui| {
ui.add_enabled_ui(can_comment, |ui| {
for (icon, tooltip, action) in [
("message-square-plus", tl!("Add comment"), SelectionAction::Note),
("highlighter", tl!("Highlight"), SelectionAction::Markup(comments::CommentTool::Highlight)),
("underline", tl!("Underline"), SelectionAction::Markup(comments::CommentTool::Underline)),
("strikethrough", tl!("Strikethrough"), SelectionAction::Markup(comments::CommentTool::StrikeOut)),
("replace", tl!("Replace text"), SelectionAction::Replace),
] {
if icons::button(ui, icon, 26.0, false, tooltip).clicked() {
chosen = Some(action);
}
}
});
if ui.add_enabled_ui(can_copy, |ui| icons::button(ui, "copy", 26.0, false, tl!("Copy"))).inner.clicked() {
chosen = Some(SelectionAction::Copy);
}
});
if ui.add_enabled_ui(can_copy, |ui| icons::button(ui, "copy", 26.0, false, tl!("Copy"))).inner.clicked() {
chosen = Some(SelectionAction::Copy);
}
});
});
});
},
);
let Some(action) = chosen else { return false };
if let SelectionAction::Copy = action {
// Copying closes the bar but keeps the words selected, for ⌘C or a second action.
+4 -4
View File
@@ -1379,7 +1379,7 @@ fn dialogs(app: &mut PdfCraftApp, ctx: &egui::Context) {
.hint_text(tl!("Search tools…"))
.desired_width(ui.available_width() - 32.0),
);
search_resp.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::TextEdit, ui.is_enabled(), tl!("Search tools…")));
search_resp.widget_info(|| egui::WidgetInfo::labeled(egui::Role::TextInput, ui.is_enabled(), tl!("Search tools…")));
if !app.pin_tool_search.is_empty() && widgets::ghost_button(ui, "x", tl!("Clear search")).clicked() {
app.pin_tool_search.clear();
}
@@ -1408,7 +1408,7 @@ fn dialogs(app: &mut PdfCraftApp, ctx: &egui::Context) {
let pinned = app.is_tool_pinned(g.id);
let (rect, resp) = ui.allocate_exact_size(egui::vec2(ui.available_width(), 44.0), egui::Sense::click());
resp.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, true, label));
resp.widget_info(|| egui::WidgetInfo::labeled(egui::Role::Button, true, label));
let press = theme::Press::track(ui, &resp);
press.wash(ui, rect, 6, false);
let body = rect.translate(press.offset());
@@ -1425,7 +1425,7 @@ fn dialogs(app: &mut PdfCraftApp, ctx: &egui::Context) {
let btn_w = 78.0;
let btn_rect =
egui::Rect::from_center_size(body.right_center() - egui::vec2(btn_w / 2.0 + 8.0, 0.0), egui::vec2(btn_w, 26.0));
let btn_resp = ui.interact(btn_rect, ui.id().with(("pin_modal_btn", g.id)), egui::Sense::click());
let btn_resp = ui.interact(btn_rect, ui.scope_id().with(("pin_modal_btn", g.id)), egui::Sense::click());
let btn_hovered = btn_resp.hovered();
let (btn_fill, btn_stroke, text_color, btn_label) = if pinned {
@@ -1436,7 +1436,7 @@ fn dialogs(app: &mut PdfCraftApp, ctx: &egui::Context) {
(egui::Color32::TRANSPARENT, egui::Stroke::new(1.0, t.border), t.text_muted, tl!("Pin"))
};
let tip = if pinned { tl!("Unpin from Home") } else { tl!("Pin to Home") };
btn_resp.widget_info(|| egui::WidgetInfo::selected(egui::WidgetType::Button, true, pinned, format!("{tip}: {label}")));
btn_resp.widget_info(|| egui::WidgetInfo::selected(egui::Role::Button, true, pinned, format!("{tip}: {label}")));
ui.painter().rect(btn_rect, egui::CornerRadius::same(6), btn_fill, btn_stroke, egui::StrokeKind::Inside);
ui.painter().text(btn_rect.center(), egui::Align2::CENTER_CENTER, btn_label, theme::medium(12.0), text_color);
+6 -6
View File
@@ -1227,9 +1227,9 @@ fn crop_input(
let cancel = Rect::from_min_size(Pos2::new(done.min.x - spacing - cancel_w, y), egui::vec2(cancel_w, 22.0));
let reset = reset_w.map(|w| Rect::from_min_size(Pos2::new(cancel.min.x - spacing - w, y), egui::vec2(w, 22.0)));
let done_id = ui.id().with("crop_pill_done").with(page).with(i);
let cancel_id = ui.id().with("crop_pill_cancel").with(page).with(i);
let reset_id = ui.id().with("crop_pill_reset").with(page).with(i);
let done_id = ui.scope_id().with("crop_pill_done").with(page).with(i);
let cancel_id = ui.scope_id().with("crop_pill_cancel").with(page).with(i);
let reset_id = ui.scope_id().with("crop_pill_reset").with(page).with(i);
let done_resp = ui.interact(done, done_id, egui::Sense::click());
let cancel_resp = ui.interact(cancel, cancel_id, egui::Sense::click());
@@ -1510,7 +1510,7 @@ fn user_box(xf: &PageXform, info: &DocInfo, page: usize, r: Rect) -> [f64; 4] {
}
pub(crate) fn image_menu_id() -> egui::Id {
egui::Id::new("image-menu")
egui::Id::unique("image-menu")
}
/// Images on a page: select, move, resize, right-click. Returns `true` when the pointer was used.
@@ -1656,14 +1656,14 @@ pub(crate) fn image_input(
}
let mut handle_drag = None;
for (h, h_pos, handle_id) in obb.handles_with_ids(ui.id().with("img_handle")) {
for (h, h_pos, handle_id) in obb.handles_with_ids(ui.scope_id().with("img_handle")) {
let handle_rect = Rect::from_center_size(h_pos, egui::vec2(18.0, 18.0));
let handle_resp = ui.interact(handle_rect, handle_id, egui::Sense::drag());
if allow_interaction && handle_resp.drag_started() {
handle_drag = Some(h);
}
}
let rot_id = ui.id().with("img_handle").with(8);
let rot_id = ui.scope_id().with("img_handle").with(8);
let rot_rect = Rect::from_center_size(if obb.is_rotated { obb.s_rot } else { knob }, egui::vec2(12.0, 12.0));
let rot_resp = ui.interact(rot_rect, rot_id, egui::Sense::drag());
let rot_drag = allow_interaction && rot_resp.drag_started();
+5 -5
View File
@@ -113,7 +113,7 @@ pub(crate) fn panel(ui: &mut egui::Ui, t: &Tokens, look: &mut AddedText, extras:
ui.label(tl!("No openly licensed document fonts found. Load a font file."));
}
Some(list) => {
let search_id = ui.id().with("installed-font-search");
let search_id = ui.scope_id().with("installed-font-search");
let mut query = ui.data(|d| d.get_temp::<String>(search_id)).unwrap_or_default();
ui.horizontal(|ui| {
ui.label(egui::RichText::new("🔍").size(12.0));
@@ -177,7 +177,7 @@ pub(crate) fn panel(ui: &mut egui::Ui, t: &Tokens, look: &mut AddedText, extras:
}
})
.response;
font_resp.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::ComboBox, ui.is_enabled(), tl!("Font")));
font_resp.widget_info(|| egui::WidgetInfo::labeled(egui::Role::ComboBox, ui.is_enabled(), tl!("Font")));
font_resp.on_hover_text(format!("{}\n{}", tl!("Font"), tl!("Thai and Arabic use regular fallback fonts when available.")));
ui.add_space(4.0);
@@ -193,7 +193,7 @@ pub(crate) fn panel(ui: &mut egui::Ui, t: &Tokens, look: &mut AddedText, extras:
}
})
.response;
size_resp.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::ComboBox, ui.is_enabled(), tl!("Font size")));
size_resp.widget_info(|| egui::WidgetInfo::labeled(egui::Role::ComboBox, ui.is_enabled(), tl!("Font size")));
size_resp.on_hover_text(tl!("Font size"));
let swatch = colour_button(ui, t, look.color);
egui::Popup::menu(&swatch).close_behavior(egui::PopupCloseBehavior::CloseOnClickOutside).show(|ui| {
@@ -273,7 +273,7 @@ pub(crate) fn panel(ui: &mut egui::Ui, t: &Tokens, look: &mut AddedText, extras:
}
})
.response;
spacing_resp.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::ComboBox, ui.is_enabled(), tl!("Line spacing")));
spacing_resp.widget_info(|| egui::WidgetInfo::labeled(egui::Role::ComboBox, ui.is_enabled(), tl!("Line spacing")));
ui.add_space(8.0);
ui.add_enabled_ui(false, |ui| {
labelled_icon(ui, t, "pilcrow", tl!("Paragraph spacing"));
@@ -364,7 +364,7 @@ fn number_with_presets(ui: &mut egui::Ui, n: Number<'_>, presets: &[f64], width:
let field = egui::DragValue::new(&mut *n.value).range(n.range).speed(n.speed).max_decimals(2).suffix(n.suffix);
let height = ui.spacing().interact_size.y;
let drag_resp = ui.add_sized([(width - PRESET_LIST - 2.0).max(30.0), height], field).labelled_by(label.0);
drag_resp.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::DragValue, ui.is_enabled(), label.1));
drag_resp.widget_info(|| egui::WidgetInfo::labeled(egui::Role::SpinButton, ui.is_enabled(), label.1));
let list = icons::button(ui, "chevron-down", PRESET_LIST, false, label.1);
egui::Popup::menu(&list).show(|ui| {
for &v in presets {
+1 -1
View File
@@ -34,7 +34,7 @@ fn tool_card(app: &mut PdfCraftApp, ui: &mut egui::Ui, t: &Tokens, g: &'static c
let mut unpin_clicked = false;
if allow_unpin && (ui.rect_contains_pointer(rect) || resp.hovered()) {
let unpin_rect = Rect::from_center_size(body.right_top() + vec2(-18.0, 18.0), vec2(22.0, 22.0));
let unpin_resp = ui.interact(unpin_rect, ui.id().with(("unpin_card_btn", g.id)), Sense::click());
let unpin_resp = ui.interact(unpin_rect, ui.scope_id().with(("unpin_card_btn", g.id)), Sense::click());
unpin_resp.widget_info(|| egui::WidgetInfo::labeled(egui::Role::Button, true, tl!("Unpin tool")));
if unpin_resp.hovered() {
ui.painter().rect_filled(unpin_rect, CornerRadius::same(4), t.pressed);
+2 -2
View File
@@ -122,7 +122,7 @@ fn tool_row(ui: &mut egui::Ui, t: &Tokens, g: &ToolGroup, is_pinned: bool) -> (e
icons::paint(ui, Rect::from_min_size(body.min + vec2(6.0, 7.0), vec2(20.0, 20.0)), g.icon, 19.0, hue(g));
let pin_rect = Rect::from_center_size(body.right_center() - vec2(14.0, 0.0), vec2(22.0, 22.0));
let pin_resp = ui.interact(pin_rect, ui.id().with(("pin_toggle_row", g.id)), Sense::click());
let pin_resp = ui.interact(pin_rect, ui.scope_id().with(("pin_toggle_row", g.id)), Sense::click());
let tip = if is_pinned { tl!("Unpin from Home") } else { tl!("Pin to Home") };
pin_resp.widget_info(|| egui::WidgetInfo::labeled(egui::Role::Button, true, tip));
let pin_hovered = pin_resp.hovered();
@@ -176,7 +176,7 @@ fn tool_row(ui: &mut egui::Ui, t: &Tokens, g: &ToolGroup, is_pinned: bool) -> (e
};
icons::paint(ui, pin_rect.shrink(3.0), "pin", 15.0, pin_tint);
let tip = if is_pinned { tl!("Unpin from Home") } else { tl!("Pin to Home") };
pin_resp.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, true, tip));
pin_resp.widget_info(|| egui::WidgetInfo::labeled(egui::Role::Button, true, tip));
if theme::hand(pin_resp).on_hover_text(tip).clicked() {
pin_clicked = true;
}
-1
View File
@@ -14,7 +14,6 @@ pub const RELEASES_PAGE: &str = "https://github.com/storytold/pdfcraft/releases"
#[cfg(not(target_arch = "wasm32"))]
pub type UpdateSource = CheckSource;
#[derive(Default)]
pub(crate) struct Updates {
#[cfg(not(target_arch = "wasm32"))]
updater: Updater,
+1 -1
View File
@@ -7863,7 +7863,7 @@ fn clicking_after_image_context_menu_action_resets_menu_state_and_updates_select
h.get_by_label("Flip horizontal").click();
h.run_steps(3);
let flag_persisted = h.ctx.data_mut(|d| d.get_persisted::<bool>(egui::Id::new("image-menu")));
let flag_persisted = h.ctx.data_mut(|d| d.get_persisted::<bool>(egui::Id::unique("image-menu")));
assert_eq!(flag_persisted, Some(false), "image-menu flag should be reset to false");
// 7. Click image 1: should switch selection to image 1