mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-10 23:01:02 +00:00
Fix #6419: Edit › Assign Profile… and Color Settings… scroll to the Color Settings
Both commands show the Separations Preview panel (#4542), whose Color Settings section, with the Assign row, comes after the plates and Proof Setup. A floated panel fits its content only up to 320 points, so the section opened out of sight and the panel looked like the wrong one. The commands now leave a one-shot flag that scrolls the section into view, without animation, the next time the panel draws. Window › Separations Preview and edits made in the panel leave the scroll alone.
This commit is contained in:
@@ -206,9 +206,13 @@ fn run_ui_part2(app: &mut VectorcraftApp, id: &str, p: &Value) -> Option<Result<
|
||||
}
|
||||
// Edit → Color Settings… / Assign Profile… (no params): show the colour-management panel
|
||||
// wherever it is, as Window › Separations Preview does (it isn't in an icon column, so a
|
||||
// flyout for it never opened: #4542).
|
||||
// flyout for it never opened: #4542), scrolled to its Color Settings section, which a short
|
||||
// window shows only after scrolling past the plates and Proof Setup (#6419).
|
||||
"edit.colorSettings" | "edit.assignProfile" if p.as_object().is_none_or(|o| o.is_empty()) => {
|
||||
crate::panel_docking::reveal_panel(app, "separations").and_then(|_| app.session.execute(id, p).map_err(|e| e.to_string()))
|
||||
crate::panel_docking::reveal_panel(app, "separations").and_then(|_| {
|
||||
app.ui.color_settings_scroll = true;
|
||||
app.session.execute(id, p).map_err(|e| e.to_string())
|
||||
})
|
||||
}
|
||||
// Outline or Preview is a setting of the active document's view.
|
||||
"view.outline" => match app.view_mut() {
|
||||
|
||||
@@ -84,6 +84,21 @@ fn profile_dropdown(ui: &mut Ui, id: &str, current: &str, kind: ProfileKind, ext
|
||||
}
|
||||
|
||||
fn settings_section(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
let top = ui.cursor().top();
|
||||
settings_rows(app, ui);
|
||||
// Edit › Color Settings… / Assign Profile… opened the panel for this section: scroll it into
|
||||
// view once, as the plates and Proof Setup above it fill a short window (#6419). At once, not
|
||||
// animated: the panel has just opened. egui moves the scroll area on a later frame, so ask for
|
||||
// one rather than wait for the pointer to move.
|
||||
if app.ui.color_settings_scroll && !ui.is_sizing_pass() {
|
||||
let rect = egui::Rect::from_x_y_ranges(ui.max_rect().x_range(), top..=ui.min_rect().bottom().max(top));
|
||||
ui.scroll_to_rect_animation(rect, Some(egui::Align::TOP), egui::style::ScrollAnimation::none());
|
||||
ui.ctx().request_repaint();
|
||||
app.ui.color_settings_scroll = false;
|
||||
}
|
||||
}
|
||||
|
||||
fn settings_rows(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
let st = cms::active_settings();
|
||||
widgets::section_header(ui, tl!("Color Settings"));
|
||||
ui.horizontal(|ui| {
|
||||
@@ -215,4 +230,55 @@ mod tests {
|
||||
assert!(panel.iter().any(|(id, _)| id == "tritanopia"));
|
||||
assert!(panel.iter().all(|(id, _)| cms::ProofTarget::parse(id).is_some_and(|t| t.id() == *id)));
|
||||
}
|
||||
|
||||
/// #6419: Edit › Assign Profile… and Color Settings… show the panel scrolled to its Color
|
||||
/// Settings section, which a window shorter than the panel (a floated panel stops at 320
|
||||
/// points) otherwise shows only after scrolling past the plates and Proof Setup. Once: a
|
||||
/// scroll away afterwards stays.
|
||||
#[test]
|
||||
fn color_settings_and_assign_profile_scroll_the_color_settings_into_view() {
|
||||
const VIEW: f32 = 120.0;
|
||||
fn find(s: &egui::Shape, text: &str) -> Option<f32> {
|
||||
match s {
|
||||
egui::Shape::Text(t) if t.galley.text() == text => Some(t.pos.y),
|
||||
egui::Shape::Vec(v) => v.iter().find_map(|s| find(s, text)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
// One frame of the panel in a scroll area VIEW points high, scrolled to `offset` when
|
||||
// given: where the section's Black Point Compensation box shows in the view.
|
||||
fn frame(ctx: &egui::Context, app: &mut VectorcraftApp, offset: Option<f32>) -> f32 {
|
||||
let mut top = 0.0;
|
||||
let mut out = ctx.run_ui(egui::RawInput::default(), |ui| {
|
||||
top = ui.cursor().top();
|
||||
let mut area = egui::ScrollArea::vertical().id_salt("separations").max_height(VIEW);
|
||||
if let Some(y) = offset {
|
||||
area = area.vertical_scroll_offset(y);
|
||||
}
|
||||
area.show(ui, |ui| show(app, ui));
|
||||
});
|
||||
out.textures_delta.clear();
|
||||
out.shapes.iter().find_map(|c| find(&c.shape, "Use Black Point Compensation")).unwrap() - top
|
||||
}
|
||||
let visible = |y: f32| (0.0..VIEW).contains(&y);
|
||||
for id in ["edit.assignProfile", "edit.colorSettings"] {
|
||||
let mut app = VectorcraftApp::new(Session::new(), Default::default());
|
||||
app.run("file.new", json!({})).unwrap();
|
||||
let ctx = egui::Context::default();
|
||||
let before = frame(&ctx, &mut app, None);
|
||||
assert!(!visible(before), "the section starts below the view: {before}");
|
||||
app.run(id, json!({})).unwrap();
|
||||
frame(&ctx, &mut app, None);
|
||||
assert!(!app.ui.color_settings_scroll);
|
||||
// egui moves a scroll area on the frame after the request and paints it moved on the
|
||||
// one after that; both ask for a repaint.
|
||||
assert!(ctx.has_requested_repaint());
|
||||
frame(&ctx, &mut app, None);
|
||||
assert!(ctx.has_requested_repaint());
|
||||
let shown = frame(&ctx, &mut app, None);
|
||||
assert!(visible(shown), "{id} scrolls the section into the view: {shown}");
|
||||
frame(&ctx, &mut app, Some(0.0));
|
||||
assert_eq!(frame(&ctx, &mut app, None), before, "scrolled back to the top, it stays there");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -392,6 +392,11 @@ pub struct UiState {
|
||||
/// That popup's first text field is still to take the keyboard.
|
||||
#[serde(skip)]
|
||||
pub transient_focus: bool,
|
||||
/// The Separations Preview panel is still to scroll its Color Settings section into view:
|
||||
/// Edit › Color Settings… and Assign Profile… show the panel for it, and the section sits below
|
||||
/// the plates and Proof Setup, out of sight in a short window (#6419).
|
||||
#[serde(skip)]
|
||||
pub color_settings_scroll: bool,
|
||||
/// Type › Find Font…'s last Find In choice (`find_font::FIND_IN`), kept while the app runs.
|
||||
#[serde(skip)]
|
||||
pub find_font_in: String,
|
||||
@@ -1009,6 +1014,7 @@ impl Default for UiState {
|
||||
open_panel: None,
|
||||
transient_panel: None,
|
||||
transient_focus: false,
|
||||
color_settings_scroll: false,
|
||||
find_font_in: String::new(),
|
||||
control_bar: false,
|
||||
control_bar_bottom: false,
|
||||
|
||||
Reference in New Issue
Block a user