Package

purescript-gojs

Repository
AdaBeat/purescript-gojs
License
BSD-2-Clause
Uploaded by
pacchettibotti
Published on
2024-01-15T19:00:35Z

This library contains "low-level" bindings for methods, properties, constructors, and static methods for the GoJS framework for building interactive diagrams.

Module structure

The module structure tries to follow the grouping in the API section of the GoJS docs, with the exception of GraphObject, which follows the class structure. The only reason for this is that the GraphObject class structure is intricate enough to be in the top-level.

Design principles

This library is still experimental so much of the below is subject to change.

Class structure

This library is kept as simple as possible. It uses a rudimentary class structure to model JavaScript classes: for example, in GoJS, there's the following class hierachy:

             ┌---- Shape 
 (abstract)  ├---- TextBlock
GraphObject -┼---- Picture                ┌---- Adornment
             ├---- Placeholder            ├---- Link
             └---- Panel -------- Part ---┴---- Node ------ Group 

In this library, this is modeled with typeclasses IsGraphObject, IsPanel etc. GraphObject being an abstract class simply means it doesn't have a corresponding opaque foreign constructor newGraphObject, unlike Shape_, Panel_ and Part_ etc.

Return types

Collections

Some methods in GoJS return collections of GraphObjects. One can have an array that looks like this, for instance:

myArr: Part[] = [new Part(), new Node(), new Group()]

Collections in PureScript are almost always homogeneous, which means every element of the collection has to be of the same type. There's several ways to encode this in PureScript, like arrays of sum types, existential types, or concrete types that can be converted to their "children". We go with the last option here. For example, if you want to call a node method in a particular element of a collection of Parts, you could do this:

...
let setOfParts = diag # _selection
case fromPart <=< setFirst $ setOfParts of
  Just node -> useNode node -- assuming useNode :: Node_ -> Effect Unit
  Nothing -> pure unit
...

Note that if the useNode function above was polymorphic in its input, we'd need to explicitly specify the type we're converting from with fromPart @Node_, otherwise we'd get an ambiguous type error, which brings us to the next section.

Polymorphic return types

Many methods return classes. In this case we do allow the caller to determine the output, by having the output type as a visible type variable. This is more or less a shorthand for calling fromPart as above, by applying the type directly. This is often needed if the output of such a function is not used by a monomorphic function. For example, consider the following code:

myNode <- someLink # _fromNode -- _fromNode :: forall @n. IsNode n => Link_ -> Maybe n
case myNode of
  Just n -> n # findColumnForLocalX_ 10.0 -- findColumnForLocalX_ :: forall p. IsPanel p => Number -> p -> Effect Number
  Nothing -> pure 20.0

The PureScript compiler can't know what the type of n should be. All it knows is that it implements the IsNode class - it is ambiguous, and so will refuse to compile this code. The solution is to type apply the output of _fromNode, like so:

myNode <- someLink # _fromNode @Group_ -- _fromNode :: Link_ -> Maybe Group_
case myNode of
  Just n -> n # findColumnForLocalX_ 10.0 -- findColumnForLocalX_ :: Number -> Group_ -> Effect Number
  Nothing -> pure 20.0

Getting and setting properties

A couple concerns with the current design:

  1. Pure getters - not referentially transparent!

An important aspect of this library is that getting properties of opaque types is not referentially transparent!

let angle = someLink # _midAngle -- say this returns 10.0
setUnsafe someLink {midAngle: 1.0}
let angle2 = someLink # _midAngle -- this will return 1.0!

This is a big break from pure FP principles, and the reason it was done this way is so that composition of getters was 1. cleaner and 2. more performant, since impure getters would imply additional function calls - an effectful computation, at the JS level, is implemented as a closure. This decision makes the code look a lot like TypeScript.

  1. Setting properties is not type-safe

This was done in order to allow deeply nested effectful setting of properties in opaque types, for example:

setUnsafe someDiagram {"toolManager.relinkingTool.temporaryLink": someLink}

An alternative to this is use a lens-based approach (so replace getters with lenses that operate on newtyped records) and have setUnsafe operate on the same lenses, except do it effectfully; so the code above would look like this:

setUnsafe someDiagram (_toolManager <<< _relinkingTool <<< _temporaryLink) someLink

This will probably be implemented in the future, as lenses also solve another problem, which is that different classes often have properties that are named the same, but with the current approach, there's no way to make the inputs polymorphic and type-safe; with lenses, they can be expressed on newtyped records that have a field named the right thing.

TODO:

  • Implement GoJS's IncrementalData
  • Support optional arguments to methods - currently most optional methods are simply required by the bindings
  • Add documentation
  • Add rest of missing Prototype methods
  • Address peppered TODOs
Modules
GoJS.Class
GoJS.Collection
GoJS.Debug
GoJS.Diagram
GoJS.Diagram.Animation.Constructors
GoJS.Diagram.Animation.Methods
GoJS.Diagram.Animation.Properties
GoJS.Diagram.AnimationManager.Constructors
GoJS.Diagram.AnimationManager.Methods
GoJS.Diagram.AnimationManager.Properties
GoJS.Diagram.AnimationManager.Static
GoJS.Diagram.AnimationTrigger.Constructors
GoJS.Diagram.AnimationTrigger.Methods
GoJS.Diagram.AnimationTrigger.Properties
GoJS.Diagram.CommandHandler.Methods
GoJS.Diagram.CommandHandler.Properties
GoJS.Diagram.CommandHandler.Types
GoJS.Diagram.Constructors
GoJS.Diagram.DiagramEvent.Properties
GoJS.Diagram.DraggingInfo.Constructors
GoJS.Diagram.DraggingInfo.Properties
GoJS.Diagram.DraggingOptions.Constructors
GoJS.Diagram.DraggingOptions.Properties
GoJS.Diagram.InputEvent.Methods
GoJS.Diagram.InputEvent.Properties
GoJS.Diagram.Layer.Constructors
GoJS.Diagram.Layer.Methods
GoJS.Diagram.Layer.Properties
GoJS.Diagram.Layout.Constants
GoJS.Diagram.Layout.Methods
GoJS.Diagram.Methods
GoJS.Diagram.Overview.Constructors
GoJS.Diagram.Overview.Properties
GoJS.Diagram.Palette.Constructors
GoJS.Diagram.Properties
GoJS.Diagram.Types
GoJS.EnumValue
GoJS.Geometry.Brush.BrushPattern
GoJS.Geometry.Brush.Methods
GoJS.Geometry.Brush.Properties
GoJS.Geometry.Brush.Static
GoJS.Geometry.Constructors
GoJS.Geometry.Margin.Constructors
GoJS.Geometry.Margin.Methods
GoJS.Geometry.Margin.Properties
GoJS.Geometry.Margin.Static
GoJS.Geometry.Methods
GoJS.Geometry.PathFigure.Constructors
GoJS.Geometry.PathFigure.Methods
GoJS.Geometry.PathFigure.Properties
GoJS.Geometry.PathSegment.Constructors
GoJS.Geometry.PathSegment.Methods
GoJS.Geometry.PathSegment.Properties
GoJS.Geometry.Point.Constructors
GoJS.Geometry.Point.Methods
GoJS.Geometry.Point.Properties
GoJS.Geometry.Point.Static
GoJS.Geometry.Properties
GoJS.Geometry.Rect.Constructors
GoJS.Geometry.Rect.Methods
GoJS.Geometry.Rect.Properties
GoJS.Geometry.Rect.Static
GoJS.Geometry.Size.Constructors
GoJS.Geometry.Size.Methods
GoJS.Geometry.Size.Properties
GoJS.Geometry.Size.Static
GoJS.Geometry.Spot
GoJS.Geometry.Spot.Methods
GoJS.Geometry.Spot.Properties
GoJS.Geometry.Spot.Static
GoJS.Geometry.Static
GoJS.Geometry.Types
GoJS.GraphObject.Constructors
GoJS.GraphObject.Methods
GoJS.GraphObject.Panel.Methods
GoJS.GraphObject.Panel.Part.Adornment.Properties
GoJS.GraphObject.Panel.Part.Link.Methods
GoJS.GraphObject.Panel.Part.Link.Properties
GoJS.GraphObject.Panel.Part.Methods
GoJS.GraphObject.Panel.Part.Node.Group.Methods
GoJS.GraphObject.Panel.Part.Node.Group.Properties
GoJS.GraphObject.Panel.Part.Node.Methods
GoJS.GraphObject.Panel.Part.Node.Properties
GoJS.GraphObject.Panel.Part.Properties
GoJS.GraphObject.Panel.Properties
GoJS.GraphObject.Picture.Methods
GoJS.GraphObject.Picture.PictureElement
GoJS.GraphObject.Picture.Properties
GoJS.GraphObject.Placeholder.Constructors
GoJS.GraphObject.Placeholder.Properties
GoJS.GraphObject.Properties
GoJS.GraphObject.Shape.Properties
GoJS.GraphObject.Shape.Static
GoJS.GraphObject.TextBlock.Properties
GoJS.GraphObject.TextBlock.Static
GoJS.GraphObject.Types
GoJS.Key
GoJS.Layout
GoJS.Layout.CircularLayout.Constructors
GoJS.Layout.CircularLayout.Methods
GoJS.Layout.CircularLayout.Properties
GoJS.Layout.ForceDirectedLayout.Constructors
GoJS.Layout.ForceDirectedLayout.Methods
GoJS.Layout.ForceDirectedLayout.Properties
GoJS.Layout.GridLayout.Constructors
GoJS.Layout.GridLayout.Properties
GoJS.Layout.LayeredDigraphLayout.Constructors
GoJS.Layout.LayeredDigraphLayout.Properties
GoJS.Layout.LayoutEdge.CircularEdge.Constructors
GoJS.Layout.LayoutEdge.ForceDirectedEdge.Constructors
GoJS.Layout.LayoutEdge.ForceDirectedEdge.Properties
GoJS.Layout.LayoutEdge.LayeredDigraphEdge.Constructors
GoJS.Layout.LayoutEdge.LayeredDigraphEdge.Properties
GoJS.Layout.LayoutEdge.Methods
GoJS.Layout.LayoutEdge.Properties
GoJS.Layout.LayoutEdge.TreeEdge.Constructors
GoJS.Layout.LayoutEdge.TreeEdge.Properties
GoJS.Layout.LayoutNetwork.Constructors
GoJS.Layout.LayoutNetwork.Methods
GoJS.Layout.LayoutNetwork.Properties
GoJS.Layout.LayoutVertex.CircularVertex.Constructors
GoJS.Layout.LayoutVertex.CircularVertex.Properties
GoJS.Layout.LayoutVertex.ForceDirectedVertex.Constructors
GoJS.Layout.LayoutVertex.ForceDirectedVertex.Properties
GoJS.Layout.LayoutVertex.LayeredDigraphVertex.Constructors
GoJS.Layout.LayoutVertex.LayeredDigraphVertex.Properties
GoJS.Layout.LayoutVertex.Methods
GoJS.Layout.LayoutVertex.Properties
GoJS.Layout.LayoutVertex.Static
GoJS.Layout.LayoutVertex.TreeVertex.Constructors
GoJS.Layout.LayoutVertex.TreeVertex.Methods
GoJS.Layout.LayoutVertex.TreeVertex.Properties
GoJS.Layout.Properties
GoJS.Layout.TreeLayout.Constructors
GoJS.Layout.TreeLayout.Properties
GoJS.Layout.Types
GoJS.Model
GoJS.Model.Binding.Constructors
GoJS.Model.Binding.Methods
GoJS.Model.Binding.Properties
GoJS.Model.Binding.Static
GoJS.Model.ChangedEvent.Constructors
GoJS.Model.ChangedEvent.Methods
GoJS.Model.ChangedEvent.Properties
GoJS.Model.Constructors
GoJS.Model.GraphLinksModel.Constructors
GoJS.Model.GraphLinksModel.Methods
GoJS.Model.GraphLinksModel.Properties
GoJS.Model.Methods
GoJS.Model.Properties
GoJS.Model.Static
GoJS.Model.Transaction.Constructors
GoJS.Model.Transaction.Methods
GoJS.Model.Transaction.Properties
GoJS.Model.TreeModel.Constructors
GoJS.Model.TreeModel.Methods
GoJS.Model.TreeModel.Properties
GoJS.Model.Types
GoJS.Model.UndoManager.Constructors
GoJS.Model.UndoManager.Methods
GoJS.Model.UndoManager.Properties
GoJS.Prototype
GoJS.RowColumnDefinition.Constructors
GoJS.RowColumnDefinition.Methods
GoJS.RowColumnDefinition.Properties
GoJS.RowColumnDefinition.Types
GoJS.Tool
GoJS.Tool.HTMLInfo.Constructors
GoJS.Tool.HTMLInfo.Properties
GoJS.Tool.LinkingBaseTool.Methods
GoJS.Tool.LinkingBaseTool.Properties
GoJS.Tool.LinkingBaseTool.Types
GoJS.Tool.Methods
GoJS.Tool.MouseDownTools
GoJS.Tool.MouseDownTools.ActionTool.Constructors
GoJS.Tool.MouseDownTools.LinkReshapingTool.Constructors
GoJS.Tool.MouseDownTools.LinkReshapingTool.Methods
GoJS.Tool.MouseDownTools.LinkReshapingTool.Properties
GoJS.Tool.MouseDownTools.RelinkingTool.Constructors
GoJS.Tool.MouseDownTools.RelinkingTool.Methods
GoJS.Tool.MouseDownTools.RelinkingTool.Properties
GoJS.Tool.MouseDownTools.ResizingTool.Constructors
GoJS.Tool.MouseDownTools.ResizingTool.Methods
GoJS.Tool.MouseDownTools.ResizingTool.Properties
GoJS.Tool.MouseDownTools.RotatingTool.Constructors
GoJS.Tool.MouseDownTools.RotatingTool.Methods
GoJS.Tool.MouseDownTools.RotatingTool.Properties
GoJS.Tool.MouseMoveTools
GoJS.Tool.MouseMoveTools.DragSelectingTool.Constructors
GoJS.Tool.MouseMoveTools.DragSelectingTool.Methods
GoJS.Tool.MouseMoveTools.DraggingTool.Constructors
GoJS.Tool.MouseMoveTools.DraggingTool.Methods
GoJS.Tool.MouseMoveTools.LinkingTool.Constructors
GoJS.Tool.MouseMoveTools.LinkingTool.Methods
GoJS.Tool.MouseMoveTools.LinkingTool.Properties
GoJS.Tool.MouseMoveTools.PanningTool.Constructors
GoJS.Tool.MouseMoveTools.PanningTool.Properties
GoJS.Tool.MouseUpTools
GoJS.Tool.MouseUpTools.ClickCreatingTool.Constructors
GoJS.Tool.MouseUpTools.ClickCreatingTool.Methods
GoJS.Tool.MouseUpTools.ClickSelectingTool.Constructors
GoJS.Tool.MouseUpTools.ContextMenuTool.Constructors
GoJS.Tool.MouseUpTools.ContextMenuTool.Methods
GoJS.Tool.MouseUpTools.ContextMenuTool.Properties
GoJS.Tool.MouseUpTools.TextEditingTool.Constructors
GoJS.Tool.MouseUpTools.TextEditingTool.Properties
GoJS.Tool.Properties
GoJS.Tool.ToolManager.Methods
GoJS.Tool.ToolManager.Properties
GoJS.Tool.Types
GoJS.Unsafe
GoJS.Unsafe.Constructor
GoJS.Unsafe.Get
GoJS.Unsafe.InstanceOf
GoJS.Unsafe.Method
GoJS.Unsafe.Prototype
GoJS.Unsafe.Set
GoJS.Unsafe.Static
Dependencies