How to Enable or Disable a Data Layer Using DataLayerManager in God’s Eye View

Use DataLayerManager.setEnabled(layerId, true|false) for explicit programmatic control or DataLayerManager.toggle(layerId) for user-driven state inversion, both of which serialize requests through per-layer toggle chains and broadcast visibility events.

The DataLayerManager class in bilawalsidhu/gods-eye-view serves as the central orchestrator for real-time geospatial overlays. Located in src/data/manager.js, it registers layer modules and manages their complete lifecycle—from initialization through activation, periodic updates, and teardown. Every data layer conforms to a standard interface exposing init, enable, disable, update, and getStats methods, allowing the manager to treat heterogeneous data sources uniformly.

Understanding the DataLayerManager Architecture

When you instantiate DataLayerManager with a Cesium viewer reference, it creates isolated toggle chains for each registered layer. These Promise chains ensure that concurrent visibility requests never interleave, preventing race conditions during asynchronous initialization. The manager tracks internal state through properties like enabled, lifecycleState, and visibilityIntentEpoch, emitting granular events that upstream UI components consume to reflect current layer status.

Programmatic Control with setEnabled()

For deterministic on/off behavior, invoke setEnabled() with the target layer ID and boolean flag. This method triggers the private _setEnabledWithIntent() routine, which increments a visibility intent epoch to supersede stale requests and queues the operation on the layer’s dedicated toggleChain.

import { DataLayerManager } from './src/data/manager.js';
import cctvLayer from './src/data/cctv.js';

const dataMgr = new DataLayerManager(viewer);
dataMgr.register(cctvLayer);

// Explicitly enable the CCTV layer
await dataMgr.setEnabled('cctv', true, {
  origin: 'programmatic',      // 'user', 'voice', or 'tool'
  signal: abortController.signal,  // Optional AbortSignal
  notificationToken: 'ui-btn-01'   // Optional correlation token
});

The origin parameter proves critical for audit trails and analytics, distinguishing between automated scripts, user clicks, and voice commands. Supplying an AbortSignal allows cancellation mid-flight; if aborted during enablement, the manager automatically invokes the layer’s disable method to ensure clean resource cleanup. See the implementation details in src/data/manager.js lines 558-568.

User-Driven Toggling with toggle()

When building UI buttons that simply flip the current state, use toggle() rather than manually checking isEffectivelyEnabled(). This convenience method inverts the effective visibility and forwards the request to _setEnabledWithIntent() with notifyWillChangeBeforeEffective: true, guaranteeing that visibility-will-change events fire before state mutation.

document.getElementById('cctv-toggle-btn').addEventListener('click', async () => {
  // Automatically switches between enabled/disabled based on current state
  const success = await dataMgr.toggle('cctv', { 
    origin: 'user',
    notificationToken: 'toggle-btn-click' 
  });
  console.log('Toggle resolved:', success);
});

Because toggle() relies on the same internal pipeline as setEnabled(), it inherits identical serialization guarantees and abort handling without requiring boilerplate state inspection code.

Listening to Visibility Lifecycle Events

Both setEnabled() and toggle() broadcast rich event payloads that you can subscribe to for UI synchronization or logging. The subscription callback receives objects containing type, layerId, enabled, and origin fields.

dataMgr.subscribe(change => {
  if (change.layerId === 'cctv') {
    switch (change.type) {
      case 'visibility-will-change':
        console.log('About to toggle CCTV...');
        break;
      case 'visibility':
        console.log(`CCTV is now ${change.enabled ? 'ON' : 'OFF'}`);
        break;
      case 'visibility-failed':
        console.error('CCTV toggle failed:', change.error);
        break;
    }
  }
});

These events enable robust UI patterns such as loading spinners during initialization, error toasts on failure, and optimistic toggle states that revert if the lifecycle encounters an exception.

Summary

  • Use setEnabled() when you need explicit control over the target state (on vs. off) and want to specify provenance through the origin parameter.
  • Use toggle() for binary switch UI elements; it automatically queries current effective state and flips it while emitting pre-change notifications.
  • Both methods serialize requests per-layer through internal toggleChain queues, preventing race conditions during concurrent operations.
  • Pass an AbortSignal to either method to cancel pending operations gracefully; the manager handles partially completed lifecycles by invoking disable cleanup routines.
  • Subscribe to visibility events to keep UI components synchronized without polling internal state.

Frequently Asked Questions

What is the difference between setEnabled() and toggle() in DataLayerManager?

setEnabled() requires you to specify the desired end state explicitly (true or false), making it ideal for programmatic workflows like voice commands or automated scene transitions. toggle() inspects the current effective state via isEffectivelyEnabled() and inverts it, making it perfect for simple UI buttons that just need to flip a layer on or off without knowing the current status.

How does DataLayerManager handle concurrent enable or disable requests?

Each registered layer maintains a private toggleChain Promise sequence. When you call setEnabled() or toggle(), the manager appends the operation to this chain via _setEnabledWithIntent(). This architecture ensures that even if a user rapidly clicks a toggle button while a previous initialization is still pending, requests execute serially rather than interleaving, preventing duplicate resources or partial initialization states.

Can I cancel a layer enable operation after calling setEnabled()?

Yes. Pass an AbortSignal through the options object when invoking setEnabled(). If the signal aborts before the lifecycle completes, the manager catches the cancellation and automatically executes the layer’s disable method to release any partially allocated resources. The system emits a visibility-cancelled event that you can observe to update UI indicators.

Where is the DataLayerManager instantiated in the God’s Eye View application?

The manager is instantiated in src/main.js during application bootstrap, receiving the Cesium viewer instance as a constructor argument. From there, it is injected into subsystems including voice command handlers (src/voice/gevActions.js) and UI controls (src/ui.js), which demonstrate real-world usage patterns for enabling and disabling data layers programmatically and interactively.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →