Skip to content

feat(layers): new layers go on top, web tile layers take a place among the map's layers (#808) - #1031

Merged
pick2510 merged 1 commit into
opengeos:mainfrom
pick2510:feat/new-layers-on-top
Oct 27, 2026
Merged

pick2510 merged 1 commit into
opengeos:mainfrom
pick2510:feat/new-layers-on-top

Conversation

@pick2510

@pick2510 pick2510 commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Newly added layers go on top of the drawing order, as in GeoLibre (the direction in #808), and web tile layers (WMS, WMTS, XYZ, vector tiles, PMTiles, MBTiles, GeoTIFFs read in place) take a place among the map's layers instead of always drawing under all of them.

New layers on top, whatever adds them

  • Feature layers go on top whatever their geometry. Before, they went in by rank: points above lines above polygons above rasters.
  • Rasters, analysis results, pasted layers and plugin layers go on top too.
  • So do tile layers added as overlays or as data: WMS/WMTS/vector services, Add Tile Layer with Overlay, and archives or GeoTIFFs from Add Data (a new "top" option of map.addTiles). Each goes above the one added before it, and the layers already there keep their order.
  • Basemaps (the gallery, Add Tile Layer without Overlay) stay under the map's layers, as GeoLibre's basemap does.
  • A new layer never goes into a layer group.
  • The QGIS import adds layers bottom first. It now gets QGIS's own order, web layers included, which the rank rule used to mix up.

Tile layers among the map's layers

  • TileLayer.over names the map layer a tile layer is drawn just over. Without it, the tile layer is drawn under all of them, which is where every tile layer of a project saved before this stays. Saved projects draw as before (tested).
  • A tile layer sits over a layer or above a whole group, never inside one. Its place is stored as the group's topmost layer, so ungrouping leaves it where it is.
  • Map::stack() is the drawing order of all layers. map.tiles is kept in that order, so index 0 is still the topmost tile layer for scripts, the pop-ups and the AI Assistant.
  • Rendering: both renderers draw each tile layer at its place: the CPU one (also used for exports and layouts) and the GPU map view (LiveTiles, tile meshes). Slots are worked out once a frame.
  • Moving and removing: moving or removing a map layer hands the tile layers drawn over it to the layer below, so they keep their place. This covers removal, group moves, packaging and templates.
  • Commands: map.setTiles move (up/down/top/bottom) now steps past map layers too, a group at once. A new to puts a tile layer at a place in the drawing order. A bad to, or move and to together, is refused.
  • Layers pane:
    • It lists tile rows at their place.
    • Move up/down and dragging move a tile row past map layers.
    • A layer dropped on the block of a layer with tile rows above it goes above those rows, as the drop line shows.
  • Basemap gallery: its ▲/▼ swap a tile layer only with its neighbour at the same place, so a basemap can't jump over the data.
  • Identify:
    • "Topmost Layer" ranks features, vector-tile features and WMS layers by drawing order, so an overlay drawn over a feature layer answers first.
    • For old projects (every tile layer under all layers) the results and WMS requests are unchanged.
    • The AI Assistant's project summary says which layer each tile layer is drawn over.

Behaviour changes for existing use

  • Insertion order: new feature and raster layers no longer go in by geometry type. This is the change [Feature]: Add newly added layers to the top of the drawing order #808 asks for. Five engine tests that pinned the old rank rule are updated to the new one.
  • Scripts: map.setTiles "move": "up"/"top" on a tile layer under all layers now moves it over map layers, where before it only moved among tile layers. Rows of the Basemap gallery keep the old among-tile-layers behaviour.

Testing

  • New tests:
    • Every way of adding a layer: polygon, raster, overlay, a later layer, basemap, top, and an MBTiles archive from Add Data drawn over the map.
    • Tile moves past layers and groups, by step and by to, and bad parameters.
    • Removal and undo; ungroup and leaving a group.
    • map.tiles order; old projects without over, and a saved place read back.
    • Rendering: on the CPU, the pixel colour with the tile layer under, over and under a later layer; on the GPU, the draw-command order.
    • The pane: listing, the Move down menu, dragging.
  • Results:
    • rustgis-map, rustgis-engine, rustgis-ui-egui and rustgis-assistant pass.
    • In rustgis-render only the two text tests that need fonts missing on my machine fail (text_takes_italic_alignment_and_letter_spacing, a_text_graphic_is_drawn_aligned_slanted_and_spaced); they fail on main here too.
    • Clippy -D warnings, cargo fmt and cargo xtask layers pass.
    • The memory guard stopped a full-workspace cargo xtask ci run on my machine, so the crates were tested one at a time. The crates this doesn't touch weren't run.
  • Not built here: the wasm build (no wasm target installed); nothing desktop-only is used.
  • Reviews: two independent read-only reviews ran before opening. Their findings are fixed: the data archives' place, places inside groups, the tile list's order, identify, rendering cost, the gallery and the drop line.
  • Screenshots: with ui_shot, the issue's GEBCO WMS on the World Atlas sample, against the real service.

UI evidence

The GEBCO WMS from #808 added with Overlay on the World Atlas sample.

Before: listed and drawn under Countries, which hides it (only the sea shows):

before

After: added on top of the map's layers:

after

After, moved between layers (map.setTiles {"to": 3}, or Move down / dragging in the Layers pane): over Countries, under Lakes, Rivers and Cities:

after, between layers

Related issue

Closes #808

Summary by CodeRabbit

  • New Features
    • Web tile layers can be positioned among map layers, displayed beneath all map layers, and reordered in the combined drawing order.
    • The Layers pane shows tile layers in their drawing positions and supports moving them alongside map layers.
    • Newly added map layers appear at the top of the drawing order. Layer listings show which map layer each tile layer sits above.
  • Bug Fixes
    • Tile positions are preserved when layers are grouped, removed, or saved and restored.
    • Feature identification now follows drawing order when selecting topmost results.
  • Documentation
    • Updated guidance on basemap placement, overlays, and layer ordering.

@coderabbitai

coderabbitai Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 37635283-01da-4622-b3c1-a210699b7af6
Commits

Reviewing files that changed from the base of the PR and between 3a2d52d and 7dec859.

Files selected for processing: 20
  • crates/assistant/src/tests.rs
  • crates/assistant/src/tools.rs
  • crates/engine/src/cmd/group.rs
  • crates/engine/src/cmd/items.rs
  • crates/engine/src/cmd/layer.rs
  • crates/engine/src/cmd/project.rs
  • crates/engine/src/cmd/raster.rs
  • crates/engine/src/cmd/select.rs
  • crates/engine/src/cmd/select_info.rs
  • crates/engine/src/cmd/tiles.rs
  • crates/engine/src/tests.rs
  • crates/map/src/lib.rs
  • crates/map/src/tiles.rs
  • crates/render/src/lib.rs
  • crates/render/src/tiles.rs
  • crates/ui-egui/src/dialogs.rs
  • crates/ui-egui/src/panes.rs
  • crates/ui-egui/src/ribbon.rs
  • docs/user-guide/index.md
  • docs/user-guide/maps.md

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 5 remain after this review.

Walkthrough

The change places tile layers within the map drawing stack. It adds placement and movement APIs, renders tiles at their configured positions, preserves placements during layer changes, updates selection and UI behavior, and documents the new ordering.

Changes: Tile drawing order

Layer / File(s) Summary
Combined map and tile stack
crates/map/src/lib.rs, crates/map/src/tiles.rs
Tile layers now store an optional over target. The map exposes combined-stack inspection, tile movement, placement, and placement preservation. New map layers are inserted at the top.
Command and selection integration
crates/engine/src/cmd/*
Tile commands expose placement and movement. Add-layer commands request top placement. Layer removal releases tile placements. identify ranks map and tile results by drawing order.
Positioned tile rendering
crates/render/src/lib.rs, crates/render/src/tiles.rs
Tile layers are drawn between map layers according to their slots. Rendering and tile-output tests cover placement behavior.
UI, context, and validation
crates/ui-egui/src/*, crates/assistant/src/*, crates/engine/src/tests.rs, docs/user-guide/*
The Layers pane, ribbon controls, assistant context, documentation, and tests now represent and validate the combined drawing order.

Priority: Normal

Estimated code review effort: 4 (Complex) | ~60 minutes

Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant LayersPane
  participant TilesCommand
  participant Map
  participant Renderer
  User->>LayersPane: move tile layer
  LayersPane->>TilesCommand: set target stack position
  TilesCommand->>Map: place_tile
  Map-->>TilesCommand: updated tile placement
  Renderer->>Map: read combined stack
  Map-->>Renderer: map layers and tile slots
  Renderer-->>User: draw tiles at configured positions
Loading

Possibly related issues

  • opengeos/RustGIS issue 808: The pull request changes new-layer insertion and tile rendering order described by the issue.

Possibly related PRs

Suggested reviewers: giswqs

Merge Risk: Moderate · up to 7dec8

Moving a layer or group to its current position can unexpectedly move tile overlays beneath map content. Resolve those ordering regressions before merging.

Pre-merge checks: Passed 5
Check name Status Explanation
Title check Passed The title clearly summarizes the two primary changes: new layers are placed on top, and web tile layers can occupy positions among map layers.
Description check Passed The description includes the required Summary, Testing, UI evidence, and Related issue sections. It explains the behavior changes, test coverage, known environment-specific failures, screenshots, and …
Linked Issues check Passed The PR addresses the active requirements in [#808]. Map::add_dataset and other layer-add paths now insert new layers at the top instead of by geometry rank. TileLayer::over, Map::stack, tile pla…
Out of Scope Changes check Passed The changed files support [#808]. Packaging and template cleanup preserve tile placement when layers are removed. Identify and AI Assistant changes expose the new drawing order. UI, documentation, and…
Docstring Coverage Passed Docstring coverage is 84.21% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Documentation-only edits and deletions within surviv…
Full details: Description check

Explanation

The description includes the required Summary, Testing, UI evidence, and Related issue sections. It explains the behavior changes, test coverage, known environment-specific failures, screenshots, and linked issue.

Full details: Linked Issues check

Explanation

The PR addresses the active requirements in [#808]. Map::add_dataset and other layer-add paths now insert new layers at the top instead of by geometry rank. TileLayer::over, Map::stack, tile placement, movement, removal, grouping, and rendering place service and raster tiles among map layers. Basemap tiles remain below map layers. The Layers pane, overlay wording, identify ordering, and AI Assistant context match the drawing order. Tests cover insertion, tile placement, legacy projects, rendering, removal, groups, and UI behavior.

Full details: Out of Scope Changes check

Explanation

The changed files support [#808]. Packaging and template cleanup preserve tile placement when layers are removed. Identify and AI Assistant changes expose the new drawing order. UI, documentation, and tests describe or verify the feature. No unrelated change is demonstrated by the reviewed summary and focused diff.

Full details: Docstring Coverage

Explanation

Docstring coverage is 84.21% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 57 functions across 17 files. (3 skipped: 2 unsupported, 1 too large.)

Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit hops where tile layers lie
Between the map and evening sky
Up goes a layer, down goes another
The stack stays neat beside its brother
The basemap rests beneath the scene
And every row knows where it’s been

Comment @coderabbitai help to get the list of available commands.

Comment thread crates/map/src/lib.rs
Comment thread crates/map/src/lib.rs
@github-actions

Copy link
Copy Markdown
Contributor

Code review

Bugs

  • Map::place_layer releases the tile layers over a layer on every call, even when the layer stays where it is. A tile layer drawn over L then drops beneath L after a no-op layer.group (for example, a Layers-pane drop onto its own spot). Confidence: medium. Inline comment posted at crates/map/src/lib.rs:1292.
  • Map::move_group has the same unconditional release, so a group move to its current position re-seats the tile layers over it. Confidence: medium. Inline comment posted at crates/map/src/lib.rs:1321.

Security

  • Nothing found. Input handling is bounded: to is parsed with as_u64, clamped with min, and out-of-range indices are checked. Panics are avoided in non-test code. Layer names in the AI context are clipped, and no credentials are added to the output.

Performance

  • Low: Map::tile_slot rebuilds units() (with HashMap allocations) once per tile. tools::context, project info and map.tiles call it in a loop, so the cost is O(tiles × layers) per call. Calling tile_slots() once would be cleaner. Confidence: high, impact small.
  • Low: the Layers pane, identify and the GPU draw loop are O(tiles × layers) per frame or per hit. Fine at realistic sizes.

Quality

  • Map::place_tile assigns t.over twice: first from the layer found in below, then from tile_slot(&t), which reads that field. It works, but a short comment or a local variable would make the intent clearer.
  • Map::lift_out reinserts the layer and then removes it again before the move. The logic is correct but hard to read.
  • The new tl! text for the Overlay checkbox changes an existing string, so existing catalog entries stop matching. AGENTS.md accepts this, so it's noted only.
  • docs/user-guide/maps.md: the blend-mode paragraph contains one very long line, out of step with the surrounding wrapping.
  • Tests cover the no-op case only for move_layer implicitly. Nothing tests a no-op layer.group or group.move, which is why the two bugs above are not caught.

AGENTS.md

  • No unwrap, expect or panic! in non-test code; every match in the diff is in a test module.
  • Layering holds: L6 uses L4 types, and no new egui code sits below L6.
  • New user-visible strings use tl!.
  • Not verified here: the wasm build and the full cargo xtask ci run. The PR says both were not run locally, so CI must cover them.

What I checked

  • The whole 1,607-line diff, the Map move, group and drawing-order code, render order, the identify ranking, the GPU live-tiles consumer, and Session::guarded rollback. Rollback means partial mutations in map.setTiles are undone on error, so that path is fine.
  • The ribbon and pane move logic: the stack-index arithmetic for "up" and "down" is correct.

Change size

Compared: the whole PR against main (merge base 3a2d52d to PR head 7dec859).

Measure Value
Files changed 20 (0 added, 20 modified, 0 removed, 0 renamed)
Size before 2.79 MB
Size after 2.82 MB
Total size change +36.3 KB
Path Before After Change
crates/map/src/lib.rs 96.7 KB 105.7 KB +9.0 KB
crates/engine/src/tests.rs 1.04 MB 1.05 MB +8.6 KB
crates/ui-egui/src/panes.rs 318.2 KB 325.7 KB +7.3 KB
crates/render/src/tiles.rs 45.1 KB 47.5 KB +2.4 KB
crates/render/src/lib.rs 355.0 KB 357.3 KB +2.3 KB
crates/engine/src/cmd/select.rs 31.3 KB 32.7 KB +1.4 KB
crates/ui-egui/src/ribbon.rs 213.9 KB 215.0 KB +1.1 KB
crates/engine/src/cmd/tiles.rs 33.3 KB 34.3 KB +1.0 KB
docs/user-guide/maps.md 30.0 KB 30.4 KB +394 B
crates/map/src/tiles.rs 24.7 KB 25.1 KB +392 B
crates/assistant/src/tools.rs 35.0 KB 35.3 KB +340 B
crates/engine/src/cmd/select_info.rs 11.7 KB 12.0 KB +323 B
crates/engine/src/cmd/items.rs 52.9 KB 53.2 KB +284 B
crates/engine/src/cmd/layer.rs 147.5 KB 147.8 KB +219 B
crates/assistant/src/tests.rs 223.5 KB 223.7 KB +192 B
crates/engine/src/cmd/group.rs 9.3 KB 9.4 KB +109 B
docs/user-guide/index.md 16.2 KB 16.3 KB +99 B
crates/ui-egui/src/dialogs.rs 87.0 KB 87.0 KB +63 B
crates/engine/src/cmd/project.rs 15.9 KB 15.9 KB +50 B
crates/engine/src/cmd/raster.rs 40.5 KB 40.5 KB +13 B

@github-actions

Copy link
Copy Markdown
Contributor

📖 Docs preview

Item Value
Preview https://preview.rustgis.app/pr-1031/
Web app https://preview.rustgis.app/pr-1031/app/
Commit 7dec859

GitHub Pages takes a minute or two to publish a new commit.

@pick2510
pick2510 merged commit 9cf3790 into opengeos:main Oct 27, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Add newly added layers to the top of the drawing order

1 participant