Each tool is a directory with a config.json plus a module exporting a small lifecycle (initialize, make, destroy, ...); the ToolController loads them from a build-time-generated src/pre/tools.js, including any plugin-drop directories.
A tool that leaks listeners in destroy() will break neighboring tools — the controller assumes destroy fully tears down whatever make set up.
What a Tool is
A "Tool" in is a single user-facing capability that takes over the side
tool panel (or a floating popout) when the user clicks its toolbar icon. Each
tool is a self-contained module under src/essence/Tools/<Name>/ — typically a
<Name>Tool.js, a config.json, a .css file, and any sub-modules it needs.
Tools are independent of each other: they read shared map state from L_, draw
on the map through Map_/Globe_/Viewer_, and otherwise mind their own
business.
The contract
Tools are plain JS objects with a small lifecycle the ToolController
calls into. From MeasureTool.js:
let MeasureTool = {
height: 243,
width: 'full',
initialize: function () { /* called once at boot */ },
make: function () { /* called when the user activates the tool */ },
destroy: function () { /* called when the tool is deactivated */ },
getUrlString: function () { /* optional — serialize state into the URL */ },
}
The full surface, all optional except make/destroy:
height,width— desired tool-panel size; the controller resizes the panel on activation.initialize()— once at boot, after all tools are registered.make(controller)— render into the#toolsdiv (or#toolPanel); attach map listeners.destroy()— tear down everythingmakeset up. Tools that leak listeners break neighbors.notify(type, payload)— sideband messages from the controller (for cross-tool events).finalize()— late hook for things that need other tools already up.getUrlString()— round-trip tool state through the URL share link.made— used by "separated" (popout) tools to track open/closed state.
The "New Tool Template" file in the tools directory is the minimum viable shape, kept in sync with this contract.
How tools are registered
Tools are not imported by hand. The Node script API/updateTools.js runs before
webpack and:
- Scans
src/essence/Tools/*for any directory containing aconfig.json. - Also scans
src/essence/*Plugin-Tools*and*Private-Tools*directories (gitignored, dropped in by integrators) for the same shape. - Sorts entries by
toolbarPriorityand writessrc/pre/tools.js— a generated file that re-exportstoolModules,toolConfigs, andKinds.
ToolController_ then imports { toolModules, toolConfigs } from that
generated module and wires up the toolbar buttons. To add a new built-in tool,
you create a directory with a config.json and a module exporting the
lifecycle object — no edits anywhere else. To ship a private tool against an
unmodified MMGIS checkout, you drop a MyOrg-Plugin-Tools/ directory next to
the standard tools and the same machinery picks it up. This is the same
convention the backend uses for *Plugin-Backend* modules.
A tool's config.json declares its name, default icon, the paths to its
modules, and a config block describing the variables it accepts — that block
is what the Configure SPA renders as a form so
mission admins can configure the tool without touching code.
Tour of the built-ins
The shipped tools cluster into a few groups:
- Map editing.
Drawis the heaviest — sub-modules for drawing, editing, history, file management, templating, and publishing real-time edits over the websocket.Measuredoes distance + elevation profiling against configurable DEMs. - Inspection.
Identifierqueries features under the cursor;Inforenders feature detail using the sharedKindsrendering registry;Layersis the layer tree and visibility/opacity controls. - Analysis.
Isochrone(travel-time polygons),Viewshed(line-of-sight),Curtain(cross-section),Chemistry(compositional plots). - Time and motion.
Animationplays through time-aware layers, working with theTimeControl_runtime described in core runtime. - Chrome and navigation.
Sites(preset locations),Legend,Shade(lighting),Kinds(the feature-detail rendering catalog used byInfo).
The also dual-emits every tool-change event onto the mmgisAPI event bus, so embedders and plugin authors can observe and drive tools from outside the page.
The Basics module that loads tools, builds the toolbar, owns activeTool, and dispatches
keyboard shortcuts. Reads its tool list from src/pre/tools.js, the file generated by
API/updateTools.js before webpack runs.
The main MMGIS browser app, under src/essence/. Bundled by the custom Webpack
pipeline. Not an idiomatic React app — a hybrid of jQuery-era imperative modules and
React 16 islands.
The public, stable JavaScript API exposed to embedders and plugin authors so they can drive MMGIS from outside.
Related
- Frontend (Essence) — Core runtime and map enginesHow Essence boots, wires up the global L_ map state, manages the panel layout, and switches between Leaflet (2D), Cesium-based Globe (3D), and the image Viewer.
- Frontend (Essence) — mmgisAPI (embed/extension surface)The public, stable JavaScript API exposed to embedders and plugin authors so they can drive MMGIS from outside.
- Configure (admin SPA)A separate React app served at /configure for managing missions, layers, datasets, and users. Has its own webpack build.