Merge pull request #164 from storytold/fix/issue-31
Fix #31: the Save Changes dialog fits its content and the window at every UI scale
This commit is contained in:
commit
1c46c4c654
|
|
@ -91,6 +91,10 @@ use crate::{VectorcraftApp, widgets};
|
|||
|
||||
type DialogResult = Result<Value, String>;
|
||||
|
||||
/// The shared dialog frame's inner margin, and the least room it leaves at the window's edges.
|
||||
const MARGIN: i8 = 22;
|
||||
const EDGE_GAP: f32 = 8.0;
|
||||
|
||||
/// How a dialog draws and applies itself. Specs start from [`DialogSpec::FORM`] and override what
|
||||
/// differs.
|
||||
pub(crate) struct DialogSpec {
|
||||
|
|
@ -298,12 +302,12 @@ pub fn show(app: &mut VectorcraftApp, ctx: &egui::Context) {
|
|||
.resizable(false)
|
||||
.title_bar(false)
|
||||
.anchor(egui::Align2::CENTER_CENTER, [0.0, -40.0])
|
||||
.frame(egui::Frame::window(&ctx.global_style()).fill(t.panel).inner_margin(egui::Margin::same(22)))
|
||||
.frame(egui::Frame::window(&ctx.global_style()).fill(t.panel).inner_margin(egui::Margin::same(MARGIN)))
|
||||
.show(ctx, |ui| {
|
||||
ui.set_min_width(spec.min_width);
|
||||
if let Some(w) = spec.max_width {
|
||||
ui.set_max_width(w);
|
||||
}
|
||||
// Never wider than the window (a large UI scale in a small window): the text wraps.
|
||||
let room = (ctx.content_rect().width() - 2.0 * (f32::from(MARGIN) + EDGE_GAP)).max(EDGE_GAP);
|
||||
ui.set_min_width(spec.min_width.min(room));
|
||||
ui.set_max_width(spec.max_width.map_or(room, |w| w.min(room)));
|
||||
ui.label(egui::RichText::new(heading.as_str()).font(theme::semibold(16.0)).color(t.text));
|
||||
ui.add_space(12.0);
|
||||
cancel = (spec.body)(app, ui, &mut d);
|
||||
|
|
@ -383,3 +387,6 @@ mod tests_print_presets;
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests_print_advanced;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests_scale;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
//! The shared dialog frame at every UI scale (Preferences → User Interface → UI Scaling zooms the
|
||||
//! whole interface, so a window holds fewer points).
|
||||
|
||||
use serde_json::json;
|
||||
use vectorcraft_engine::Session;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// The save prompt's rect after a few frames in a window of `physical` pixels at UI scale `zoom`.
|
||||
fn prompt(app: &mut VectorcraftApp, ctx: &egui::Context, physical: egui::Vec2, zoom: f32) -> (egui::Rect, egui::Rect) {
|
||||
ctx.set_zoom_factor(zoom);
|
||||
let screen = egui::Rect::from_min_size(egui::Pos2::ZERO, physical / zoom);
|
||||
for _ in 0..10 {
|
||||
let input = egui::RawInput { screen_rect: Some(screen), ..Default::default() };
|
||||
ctx.run_ui(input, |ui| show(app, ui.ctx())).textures_delta.clear();
|
||||
}
|
||||
let rect = ctx.memory(|m| m.area_rect(egui::Id::new(("dialog", crate::unsaved::KIND)))).unwrap();
|
||||
(rect, screen)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_save_prompt_fits_its_content_and_the_window_at_every_ui_scale() {
|
||||
let mut app = VectorcraftApp::new(Session::new(), Default::default());
|
||||
app.run("file.new", json!({"width": 200, "height": 200})).unwrap();
|
||||
let ctx = egui::Context::default();
|
||||
theme::install_fonts(&ctx);
|
||||
theme::apply(&ctx, Default::default());
|
||||
for name in ["Untitled-1", "Quarterly campaign poster, final revision with the printer's notes"] {
|
||||
app.ui.dialog = Some(Dialog::new(crate::unsaved::KIND, json!({"index": 0, "name": name, "then": "close"})));
|
||||
// Scaled up and down while the prompt is open, in a full-size and in the smallest window.
|
||||
for (w, h, zoom) in
|
||||
[(1440.0, 900.0, 1.0), (1440.0, 900.0, 2.0), (1440.0, 900.0, 1.5), (800.0, 500.0, 2.0), (800.0, 500.0, 1.0), (1440.0, 900.0, 0.75)]
|
||||
{
|
||||
let (rect, screen) = prompt(&mut app, &ctx, egui::vec2(w, h), zoom);
|
||||
let at = format!("{name}: {w} × {h} px at {zoom}×: {rect:?} in {screen:?}");
|
||||
assert!(screen.contains_rect(rect), "inside the window, {at}");
|
||||
// As tall as its text and buttons (no empty band around the buttons).
|
||||
assert!(rect.height() < 200.0, "{at}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue