Module

Hylograph.ForceEngine.Halogen

Package
purescript-hylograph-simulation-halogen
Repository
afcondon/purescript-hylograph-simulation-halogen

Halogen Integration for Force Simulations

Provides subscription-based API for integrating simulations with Halogen components.

Recommended: High-Level API with Unified Events

import Hylograph.Simulation (runSimulation, SimulationEvent(..))
import Hylograph.ForceEngine.Halogen (toHalogenEmitter)

handleAction Initialize = do
  { handle, events } <- liftEffect $ runSimulation config
  halogenEmitter <- liftEffect $ toHalogenEmitter events
  void $ H.subscribe $ halogenEmitter <#> SimEvent

handleAction (SimEvent event) = case event of
  Tick { alpha } -> H.modify_ _ { alpha = alpha }
  Completed -> liftEffect $ log "Done!"
  _ -> pure unit

Legacy: Low-Level D3 Kernel API

For advanced use cases requiring direct D3 callback control:

handleAction Initialize = do
  callbacks <- liftEffect defaultCallbacks
  sim <- liftEffect $ createWithCallbacks config callbacks
  emitter <- liftEffect $ subscribeToSimulation sim
  void $ H.subscribe $ emitter <#> SimulationEvent

#toHalogenEmitter Source

toHalogenEmitter :: SimulationEmitter -> Effect (Emitter SimulationEvent)

Convert a framework-agnostic SimulationEmitter to Halogen's Emitter.

This is the recommended way to integrate simulations with Halogen. It works with both D3 and WASM engines using the same event model.

import Hylograph.Simulation (runSimulation, SimulationEvent(..))
import Hylograph.ForceEngine.Halogen (toHalogenEmitter)

handleAction Initialize = do
  { handle, events } <- liftEffect $ runSimulation config
  halogenEmitter <- liftEffect $ toHalogenEmitter events
  void $ H.subscribe $ halogenEmitter <#> SimEvent

handleAction (SimEvent event) = case event of
  Tick { alpha, nodeCount } -> do
    H.modify_ _ { alpha = alpha }
  Completed -> do
    liftEffect $ log "Simulation converged!"
  Started -> pure unit
  Stopped -> pure unit

#subscribeToSimulation Source

subscribeToSimulation :: forall row linkRow. Simulation row linkRow -> Effect (Emitter D3SimulationEvent)

Create a Halogen subscription emitter for simulation events.

This function wires up the simulation's callback system to emit Halogen-compatible events. The emitter can be used with H.subscribe.

Note: The simulation must have been created with createWithCallbacks. If created with plain create, this function returns an emitter that never fires.

Example:

-- In Halogen component Initialize:
callbacks <- liftEffect defaultCallbacks
sim <- liftEffect $ createWithCallbacks config callbacks
emitter <- liftEffect $ subscribeToSimulation sim
void $ H.subscribe $ emitter <#> SimulationEvent

-- In handleAction:
handleAction (SimulationEvent event) = case event of
  Tick -> liftEffect updateDOMPositions
  Started -> H.modify_ _ { simRunning = true }
  Stopped -> H.modify_ _ { simRunning = false }
  AlphaDecayed alpha -> when (alpha < 0.1) doSomething

#subscribeToGroup Source

subscribeToGroup :: forall row linkRow. SimulationGroup row linkRow -> Effect (Emitter D3SimulationEvent)

Create a Halogen subscription emitter for a simulation group.

This provides a single subscription for multiple synchronized simulations. The group must have been created with createGroupWithCallbacks.

Example:

callbacks <- liftEffect defaultCallbacks
group <- liftEffect $ createGroupWithCallbacks 6 defaultConfig callbacks
emitter <- liftEffect $ subscribeToGroup group
void $ H.subscribe $ emitter <#> \event -> case event of
  Tick -> UpdateAllGraphPositions
  Started -> H.modify_ _ { simRunning = true }
  Stopped -> H.modify_ _ { simRunning = false }
  _ -> pure unit
liftEffect $ startGroup group

#D3SimulationEvent Source

Re-exports from Hylograph.Simulation.Emitter

#SimulationEmitter Source

newtype SimulationEmitter

Framework-agnostic event emitter

This is intentionally opaque - use subscribe to listen for events. The internal representation is a list of listeners with unique IDs.