Skip to content

Mouse coordinates format is now multi-map aware#1598

Draft
Copilot wants to merge 7 commits intomasterfrom
copilot/fix-mouse-coordinates-format
Draft

Mouse coordinates format is now multi-map aware#1598
Copilot wants to merge 7 commits intomasterfrom
copilot/fix-mouse-coordinates-format

Conversation

Copy link
Contributor

Copilot AI commented Mar 11, 2026

In multi-map configurations where maps use different coordinate systems (e.g. one geographic/degrees, one projected/meters), the same global format string was applied to all maps — resulting in nonsensical output like Lon: 1234567, Lat: 9876543 m.

Approach

Each map in a multi-map config now carries an optional coordinate format override. When the active map has one set and no global display projection is configured (coordinates are in the map's native CRS), the per-map format is used instead of the global format.

Changes

  • MapInfo / IBranchedMapSubState — Added optional coordinateFormat?: string field to carry a per-map format override through init and into Redux state.

  • setupMaps (init-mapguide.ts) — Auto-detects non-geographic maps (via OL projection units check) when no global DisplayProjection is configured and assigns a sensible default override "X: {x}, Y: {y} {units}". Geographic maps (degrees) remain unchanged.

  • useActiveMapCoordinateFormat hook — New hook in hooks-mapguide.ts that reads the active map's coordinate format override from state.

  • MouseCoordinatesContainer — Applies the per-map format override when present and no global display projection is active; falls back to global format otherwise:

// projection = global DisplayProjection (if any)
// mapCoordinateFormat = per-map override stored in Redux state
const effectiveFormat = (!projection && mapCoordinateFormat) ? mapCoordinateFormat : format;

When a global DisplayProjection is configured, all maps transform coordinates into that projection's CRS, so the global format remains authoritative.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • storybook.js.org
    • Triggering command: /opt/hostedtoolcache/node/24.14.0/x64/bin/node /opt/hostedtoolcache/node/24.14.0/x64/bin/node /home/REDACTED/work/mapguide-react-layout/mapguide-react-layout/node_modules/.bin/storybook build -c .storybook (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Mouse coordinates format should be multi-map aware</issue_title>
<issue_description>Load any multi-map appdef whose maps coordinate system's are based in different units and the mouse coordinates will apply the same label for both resulting in non-sensical things like:

Lon: some other meters-based value, Lat: some other meters-based value deg

To fix this, we need each map in a multi-map configuration to carry an optional label override and this component should use the override for the active map if present before falling back to default label formatting behavior.</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: jumpinjackie <563860+jumpinjackie@users.noreply.github.com>
@coveralls
Copy link

coveralls commented Mar 11, 2026

Coverage Status

coverage: 38.084% (-0.02%) from 38.105%
when pulling 1e5b90e on copilot/fix-mouse-coordinates-format
into 052f108 on master.

Copilot AI changed the title [WIP] Fix mouse coordinates format for multi-map awareness Mouse coordinates format is now multi-map aware Mar 11, 2026
@jumpinjackie
Copy link
Owner

@copilot Integrate latest changes from master and revalidate your current work

Copy link
Contributor Author

Copilot AI commented Mar 13, 2026

@copilot Integrate latest changes from master and revalidate your current work

Done. Merged the latest master changes (map swipe feature and other fixes) into the branch. All 650 tests pass after the merge. Commit: 7ddc666

@jumpinjackie
Copy link
Owner

@copilot Have post-merge build errors. Pls fix.

ERROR in /home/runner/work/mapguide-react-layout/mapguide-react-layout/test/api/registry/command.spec.ts
78:25-105:41
[tsl] ERROR in /home/runner/work/mapguide-react-layout/mapguide-react-layout/test/api/registry/command.spec.ts(78,26)
      TS2352: Conversion of type '{ externalBaseLayers: never[]; initialExternalLayers: never[]; currentView: undefined; initialView: undefined; history: never[]; historyIndex: number; generic: undefined; clientSelection: undefined; mapguide: { ...; }; layers: never[]; }' to type 'IBranchedMapSubState' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Property 'coordinateFormat' is missing in type '{ externalBaseLayers: never[]; initialExternalLayers: never[]; currentView: undefined; initialView: undefined; history: never[]; historyIndex: number; generic: undefined; clientSelection: undefined; mapguide: { ...; }; layers: never[]; }' but required in type 'IBranchedMapSubState'.

ERROR in /home/runner/work/mapguide-react-layout/mapguide-react-layout/test/api/registry/command.spec.ts
124:25-149:41
[tsl] ERROR in /home/runner/work/mapguide-react-layout/mapguide-react-layout/test/api/registry/command.spec.ts(124,26)
      TS2352: Conversion of type '{ externalBaseLayers: never[]; initialExternalLayers: never[]; currentView: undefined; initialView: undefined; history: never[]; historyIndex: number; generic: undefined; clientSelection: undefined; mapguide: { ...; }; layers: never[]; }' to type 'IBranchedMapSubState' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Property 'coordinateFormat' is missing in type '{ externalBaseLayers: never[]; initialExternalLayers: never[]; currentView: undefined; initialView: undefined; history: never[]; historyIndex: number; generic: undefined; clientSelection: undefined; mapguide: { ...; }; layers: never[]; }' but required in type 'IBranchedMapSubState'.

ERROR in /home/runner/work/mapguide-react-layout/mapguide-react-layout/test/api/registry/command.spec.ts
173:25-198:41
[tsl] ERROR in /home/runner/work/mapguide-react-layout/mapguide-react-layout/test/api/registry/command.spec.ts(173,26)
      TS2352: Conversion of type '{ externalBaseLayers: never[]; initialExternalLayers: never[]; currentView: undefined; initialView: undefined; history: never[]; historyIndex: number; generic: undefined; clientSelection: undefined; mapguide: { ...; }; layers: never[]; }' to type 'IBranchedMapSubState' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Property 'coordinateFormat' is missing in type '{ externalBaseLayers: never[]; initialExternalLayers: never[]; currentView: undefined; initialView: undefined; history: never[]; historyIndex: number; generic: undefined; clientSelection: undefined; mapguide: { ...; }; layers: never[]; }' but required in type 'IBranchedMapSubState'.

ERROR in /home/runner/work/mapguide-react-layout/mapguide-react-layout/test/api/registry/command.spec.ts
213:25-238:41
[tsl] ERROR in /home/runner/work/mapguide-react-layout/mapguide-react-layout/test/api/registry/command.spec.ts(213,26)
      TS2352: Conversion of type '{ externalBaseLayers: never[]; initialExternalLayers: never[]; currentView: undefined; initialView: undefined; history: never[]; historyIndex: number; generic: undefined; clientSelection: undefined; mapguide: { ...; }; layers: never[]; }' to type 'IBranchedMapSubState' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Property 'coordinateFormat' is missing in type '{ externalBaseLayers: never[]; initialExternalLayers: never[]; currentView: undefined; initialView: undefined; history: never[]; historyIndex: number; generic: undefined; clientSelection: undefined; mapguide: { ...; }; layers: never[]; }' but required in type 'IBranchedMapSubState'.

…ired-nullable

Co-authored-by: jumpinjackie <563860+jumpinjackie@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 14, 2026

@copilot Have post-merge build errors. Pls fix.

...

Fixed in ea37e81. The coordinateFormat field in IBranchedMapSubState was declared as coordinateFormat: string | undefined (required property), which caused TS2352 errors in test fixtures that don't include it. Changed it to coordinateFormat?: string (optional) — all 650 tests now pass.

@jumpinjackie
Copy link
Owner

@copilot What would be a suitable manual test plan to verify this works?

Copy link
Contributor Author

Copilot AI commented Mar 14, 2026

@copilot What would be a suitable manual test plan to verify this works?

Here's a suitable manual test plan:

Prerequisites

  • A MapGuide Server instance with an Application Definition (appdef) that configures at least two maps in different coordinate systems — one geographic (degrees, e.g. WGS84 / EPSG:4326) and one projected (meters, e.g. BC Albers / EPSG:3005 or UTM).
  • The viewer built and served with these changes.

Test Case 1 — Projected map shows X/Y format

  1. Load the multi-map appdef in the viewer.
  2. Ensure the active map is the projected (meters-based) map.
  3. Move the mouse over the map.
  4. Expected: Mouse coordinates display as X: <easting>, Y: <northing> m (or the units of that CRS). No geographic labels (Lon/Lat/deg) should appear.

Test Case 2 — Geographic map shows Lon/Lat format

  1. Switch the active map to the geographic (degrees-based) map.
  2. Move the mouse over the map.
  3. Expected: Mouse coordinates display in the global format (e.g. Lon: <x>, Lat: <y> deg). The per-map override should not apply here since the map CRS is geographic.

Test Case 3 — Switching between maps updates format

  1. With the multi-map viewer loaded, start on the geographic map and confirm Lon/Lat format.
  2. Switch to the projected map.
  3. Expected: Format immediately changes to X/Y format without a page reload.
  4. Switch back to the geographic map.
  5. Expected: Format reverts to Lon/Lat format.

Test Case 4 — Global DisplayProjection takes precedence

  1. Configure a global DisplayProjection in the appdef (e.g. reproject all coordinates to EPSG:4326).
  2. Load the viewer and switch between maps.
  3. Expected: All maps display coordinates using the global format string (the per-map override is ignored when a global display projection is active).

Test Case 5 — Single-map appdef is unaffected

  1. Load a single-map appdef (any CRS).
  2. Move the mouse over the map.
  3. Expected: Behaviour is identical to before this change — the global format string is used.

@jumpinjackie
Copy link
Owner

@copilot Manually resolved merge conflicts. Pls revalidate your current work.

Co-authored-by: jumpinjackie <563860+jumpinjackie@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 14, 2026

@copilot Manually resolved merge conflicts. Pls revalidate your current work.

Revalidated. The manual merge conflict resolution had dropped the /** opening tag from the mapDef JSDoc comment in defs.ts, causing a parse error that failed 10 test suites. Fixed in 0b08800 — all 665 tests now pass.

@jumpinjackie
Copy link
Owner

@copilot What settings do I need to put into my appdef to test this?

Copy link
Contributor Author

Copilot AI commented Mar 14, 2026

@copilot What settings do I need to put into my appdef to test this?

No special appdef settings are required — the coordinate format override is detected and applied automatically at init time.

What you need in the appdef:

A standard multi-map MapSet with two MapGroup entries pointing to map definitions in different coordinate systems — one geographic (degrees, e.g. WGS84/EPSG:4326) and one projected (meters or feet, e.g. BC Albers/EPSG:3005 or any UTM zone):

<MapSet>
  <MapGroup id="Map1">
    <Map>
      <Type>MapGuide</Type>
      <Extension>
        <ResourceId>Library://Samples/Sheboygan/Maps/Sheboygan.MapDefinition</ResourceId>
        <!-- ^ geographic (WGS84/degrees) map -->
      </Extension>
    </Map>
  </MapGroup>
  <MapGroup id="Map2">
    <Map>
      <Type>MapGuide</Type>
      <Extension>
        <ResourceId>Library://Samples/SomeProjectedMap.MapDefinition</ResourceId>
        <!-- ^ projected (meters-based) map -->
      </Extension>
    </Map>
  </MapGroup>
</MapSet>

What happens automatically:

  • At init, the viewer checks each map's EPSG code via OL's projection registry.
  • If a map's native CRS uses non-degree units (m, ft, etc.) and no global DisplayProjection is set on the CursorPosition widget, it gets a coordinateFormat override of "X: {x}, Y: {y} {units}".
  • Geographic maps (degrees) are left unchanged and use the global format (e.g. Lon: {x}, Lat: {y} {units}).

To also test the "global projection overrides per-map format" case (Test Case 4): add a CursorPosition widget with a DisplayProjection value — this re-enables the global format for all maps.

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.

Mouse coordinates format should be multi-map aware

3 participants