mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-31 21:27:00 -06:00
Presentation Mode fits the active artboard and hides selections, guides, grids and artboard edges
This commit is contained in:
@@ -73,6 +73,7 @@ impl VectorcraftApp {
|
||||
cursors: Default::default(),
|
||||
view_moved: None,
|
||||
hover_cursor: None,
|
||||
presented: None,
|
||||
},
|
||||
perf: Perf::default(),
|
||||
dock_rt: Default::default(),
|
||||
|
||||
@@ -55,6 +55,9 @@ pub struct CanvasCache {
|
||||
/// The cursor the active tool last gave over the canvas, with the tool and the modifier keys
|
||||
/// it was for: kept while the view moves.
|
||||
pub hover_cursor: Option<(&'static str, vectorcraft_tools::Mods, vectorcraft_tools::Cursor)>,
|
||||
/// In Presentation Mode, the canvas rect the active artboard was last fitted to: it is fitted
|
||||
/// again when the rect changes (the window going full screen).
|
||||
pub presented: Option<egui::Rect>,
|
||||
}
|
||||
|
||||
/// [`CanvasCache::slices`]: the layout of the slices of (document uid, revision).
|
||||
|
||||
@@ -207,9 +207,13 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
let rect = rect.round_to_pixels(ui.ctx().pixels_per_point());
|
||||
app.canvas_rect = Some(rect);
|
||||
let fitted = app.view().is_some_and(|v| v.fitted);
|
||||
if !fitted {
|
||||
// Presentation Mode shows the active artboard on the whole screen and nothing but the art:
|
||||
// no selection, guides, grids or artboard edges (#4365).
|
||||
let presenting = app.ui.screen_mode == 3;
|
||||
if !fitted || (presenting && app.canvas.presented != Some(rect)) {
|
||||
fit(app, "view.fitArtboard");
|
||||
}
|
||||
app.canvas.presented = presenting.then_some(rect);
|
||||
// Before the canvas's own interaction, so the view the canvas draws is the one they moved to.
|
||||
if bars {
|
||||
scroll_bars(app, ui, rect, outer, &t);
|
||||
@@ -238,7 +242,7 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
|
||||
paint_paper(app, ui, &painter, &xf, rect, &t);
|
||||
// The grid behind the art (Guides & Grid › Grids In Back), else over it below.
|
||||
let grid_look = app.ui.view.grid.then(|| LineLook::grid(&app.session.prefs));
|
||||
let grid_look = (app.ui.view.grid && !presenting).then(|| LineLook::grid(&app.session.prefs));
|
||||
let grids_in_back = app.session.prefs.grids_in_back;
|
||||
if let Some(look) = grid_look.filter(|_| grids_in_back) {
|
||||
grid(&painter, &xf, doc.grid.spacing, doc.grid.subdivisions, look);
|
||||
@@ -293,28 +297,30 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
}
|
||||
// The pixel grid (Guides & Grid › Show Pixel Grid (Above 600% Zoom)): in Pixel Preview from
|
||||
// 600% zoom, a line at every document pixel over the art, so the pixels it rasterizes to show.
|
||||
if app.ui.view.pixel_preview && v.zoom >= PIXEL_GRID_ZOOM && app.session.prefs.show_pixel_grid {
|
||||
grid(&painter, &xf, 1.0, 1, LineLook { color: PIXEL_GRID, dots: false });
|
||||
}
|
||||
artboard_outlines(app, ui, &painter, &xf, &t);
|
||||
if app.ui.view.guides {
|
||||
guide_lines(app, &painter, &xf, rect, &t);
|
||||
}
|
||||
|
||||
if !app.session.slices_hidden() {
|
||||
slice_overlay(app, &painter, &xf);
|
||||
}
|
||||
if app.session.active().is_some_and(|d| d.print_tiling) || app.session.tool_id() == "printTiling" {
|
||||
print_tiling_overlay(app, &painter, &xf);
|
||||
}
|
||||
original_path_overlay(app, &painter, &xf);
|
||||
|
||||
let revolve_edit = app.ui.dialog.as_ref().is_some_and(crate::dialogs::revolve_gizmo::active);
|
||||
let view_info = app.view_info();
|
||||
let overlays = selection_visuals(app, &painter, &xf, (hidden_chars, hover_still), revolve_edit, view_info);
|
||||
draw_overlays(&painter, &xf, &overlays, &t, HandleLook::of(&app.session.prefs));
|
||||
if !revolve_edit {
|
||||
shaper_widget_overlay(app, &painter, &xf);
|
||||
if !presenting {
|
||||
if app.ui.view.pixel_preview && v.zoom >= PIXEL_GRID_ZOOM && app.session.prefs.show_pixel_grid {
|
||||
grid(&painter, &xf, 1.0, 1, LineLook { color: PIXEL_GRID, dots: false });
|
||||
}
|
||||
artboard_outlines(app, ui, &painter, &xf, &t);
|
||||
if app.ui.view.guides {
|
||||
guide_lines(app, &painter, &xf, rect, &t);
|
||||
}
|
||||
|
||||
if !app.session.slices_hidden() {
|
||||
slice_overlay(app, &painter, &xf);
|
||||
}
|
||||
if app.session.active().is_some_and(|d| d.print_tiling) || app.session.tool_id() == "printTiling" {
|
||||
print_tiling_overlay(app, &painter, &xf);
|
||||
}
|
||||
original_path_overlay(app, &painter, &xf);
|
||||
|
||||
let overlays = selection_visuals(app, &painter, &xf, (hidden_chars, hover_still), revolve_edit, view_info);
|
||||
draw_overlays(&painter, &xf, &overlays, &t, HandleLook::of(&app.session.prefs));
|
||||
if !revolve_edit {
|
||||
shaper_widget_overlay(app, &painter, &xf);
|
||||
}
|
||||
}
|
||||
ime_geometry(app, ui.ctx(), &xf);
|
||||
crate::place::paint_drop_highlight(app, ui.ctx(), &painter, rect);
|
||||
|
||||
@@ -273,3 +273,37 @@ fn the_screen_mode_is_not_saved() {
|
||||
let old: crate::state::UiState = serde_json::from_value(json!({ "screen_mode": 3 })).unwrap();
|
||||
assert_eq!(old.screen_mode, 0);
|
||||
}
|
||||
|
||||
/// Presentation Mode shows the active artboard fitted to the canvas, again when the canvas changes
|
||||
/// size (the window going full screen), and none of the selection's handles or the artboard edges.
|
||||
#[test]
|
||||
fn presentation_mode_fits_the_artboard_and_hides_the_selection() {
|
||||
let ctx = egui::Context::default();
|
||||
let mut app = VectorcraftApp::new(Session::new(), crate::Services::default());
|
||||
app.run("file.new", json!({"width": 200, "height": 100})).unwrap();
|
||||
app.run("shape.rectangle", json!({"x": 90, "y": 40, "width": 20, "height": 20})).unwrap();
|
||||
app.select_tool("selection");
|
||||
frame(&mut app, &ctx, vec![]);
|
||||
app.view_mut().unwrap().zoom = 0.5;
|
||||
let selection = crate::theme::Tokens::get(&ctx).selection;
|
||||
let handles = |out: &egui::FullOutput| {
|
||||
out.shapes.iter().filter(|s| matches!(&s.shape, egui::Shape::Rect(r) if r.stroke.color == selection || r.fill == selection)).count()
|
||||
};
|
||||
let before = frame(&mut app, &ctx, vec![]);
|
||||
assert!(handles(&before) > 0, "the selection's handles show");
|
||||
app.run("view.presentation", json!({})).unwrap();
|
||||
let out = frame(&mut app, &ctx, vec![]);
|
||||
let canvas = app.canvas_rect.unwrap();
|
||||
let zoom = app.view().unwrap().zoom;
|
||||
// 200 × 100 pt fitted to the canvas: one side reaches across most of it.
|
||||
assert!(200.0 * zoom >= f64::from(canvas.width()) * 0.8 || 100.0 * zoom >= f64::from(canvas.height()) * 0.8, "fitted: {zoom} in {canvas:?}");
|
||||
assert_eq!(handles(&out), 0, "no selection shows");
|
||||
// A bigger canvas (the window gone full screen) fits it again.
|
||||
let raw = egui::RawInput { screen_rect: Some(egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(1600.0, 1200.0))), ..Default::default() };
|
||||
let mut big = ctx.run_ui(raw, |ui| {
|
||||
app.logic(ui.ctx());
|
||||
app.ui(ui);
|
||||
});
|
||||
big.textures_delta.clear();
|
||||
assert!(app.view().unwrap().zoom > zoom * 1.5, "fitted again to the larger canvas");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Parity with Adobe Illustrator
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-30 · **Change:** minor (Color Effects add-on: Select by Color Kind; scores unchanged) · **Target:** Adobe Illustrator 2026 (30.x; public release notes through 30.7, August 2026)
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-30 · **Change:** minor (Presentation Mode fits the active artboard and hides selections, guides, grids and artboard edges; scores unchanged) · **Target:** Adobe Illustrator 2026 (30.x; public release notes through 30.7, August 2026)
|
||||
|
||||
## Feature submission evidence
|
||||
|
||||
@@ -764,6 +764,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
- **Views:** the status bar's artboard navigator (first, previous, next, last; `view.goToArtboard`) goes to an artboard, fits it and synchronizes the Artboard tool selection when that tool is active; ordinary object selection is preserved. Actual Next-button regressions cover keyboard/Properties deletion and Undo in `chrome.rs`. Fit Artboard in Window and Actual Size show the navigator's artboard. The Artboards panel highlights that active artboard: clicking a row makes it active (the Artboard tool's too, while it is chosen) as does clicking an artboard with the Artboard tool, double-clicking its number also fits it in the window and double-clicking its name renames it. Duplicate Artboards, or a row dragged onto New Artboard, copies the artboard with its art (#446). Escape leaves Presentation Mode, `view.screenMode` from it goes back to Normal Screen Mode, and the screen mode isn't saved with the preferences: the app always starts in Normal Screen Mode with its menus and panels (#472). View › Pixel Preview shows the art as the document pixels it rasterizes to, one per point and hard-edged when magnified, turning with a rotated view (it used to draw the smooth vectors, with only the pixel grid over them). In Outline view a template layer keeps drawing in Preview, dimmed, so a picture placed to be traced stays visible under the outlines (#1505, fixes #1486).
|
||||
In Presentation Mode, → and ← go to the next and the previous artboard, and a click anywhere goes to the next one, as the status bar navigator's Next and Previous do (`view.goToArtboard`): on the last artboard → and a click leave the view as it is, and so does ← on the first. The arrow keys do not move the selection there, and the tool does not receive a click, so a click selects and draws nothing (behavior reference: [View artwork](https://helpx.adobe.com/illustrator/using/viewing-artwork.html)).
|
||||
Full Screen Mode and Presentation Mode put the window full screen, covering the taskbar and the window's frame, and Normal Screen Mode or Full Screen Mode with Menu Bar puts it back (#4365); a window the user made full screen stays so.
|
||||
Presentation Mode shows the active artboard fitted to the screen (fitted again as the window goes full screen) and hides the selection, guides, grids, slices and the artboards' edges and names, as [presentation mode](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/view-artwork-in-presentation-mode.html) describes.
|
||||
In Presentation Mode no key press other than ←, → and Escape runs a command or reaches the tool (tool keys, Delete, Enter, Tab, F, Shift+F and every command shortcut, the macOS menu bar's key equivalents included), a right click or a long touch opens no context menu, a tap of two or three fingers undoes or redoes nothing, and the pointer over the canvas is the default one instead of the tool's cursor.
|
||||
Align to Artboard uses the active artboard, the one the Artboards panel highlights (`object.align {artboard}`). A press with a selection tool inside an artboard makes that artboard active; with the Selection tool, a Shift-click on an empty spot inside an artboard makes it active and keeps the selection. One selected object is aligned to the active artboard too, whatever Align To says (a lone object is never the key object). When an action plays, its Align to Artboard, All on Active Artboard, Paste in Place, Paste in Front and Paste in Back steps that name no artboard use the artboard that is active then.
|
||||
With the Artboard tool in use, a Shift-click on a row of the Artboards panel selects the artboards from the last row clicked without Shift to the clicked row, and the clicked row's artboard becomes the active one. When the artboard of the last row clicked without Shift is no longer selected, the range starts from the active artboard, and later Shift-clicks start from there too. A Ctrl/Cmd-click still adds or removes one artboard. A Shift-click used to add or remove one artboard as well. The public [Select artboards](https://helpx.adobe.com/illustrator/desktop/create-manage-artboards/add-edit-artboards/select-artboards.html) page lists Shift-click in the Artboards panel for selecting several artboards.
|
||||
@@ -1266,6 +1267,7 @@ spot colours, carry a colour adjustment, or are RGB, CMYK or grayscale images
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-30 | minor | Presentation Mode fits the active artboard and hides selections, guides, grids and artboard edges; scores and estimates unchanged |
|
||||
| 2026-10-30 | minor | Color Effects add-on: Select by Color Kind; scores and estimates unchanged |
|
||||
| 2026-10-30 | minor | Gradient stop popover: an eyedropper samples the stop's colour from the art (#4681); scores and estimates unchanged |
|
||||
| 2026-10-30 | minor | Full Screen and Presentation Mode fill the screen (#4365); scores and estimates unchanged |
|
||||
|
||||
Reference in New Issue
Block a user