Skip to content

Commit

Permalink
Show unconnected nodes in kdmoncat (#326)
Browse files Browse the repository at this point in the history
* Show unconnected operators in kdmoncat (#312)

* Add direct conversion of operator to kdmoncat pixels

(code not used since it needs a rotated layout in kdmoncat)

* Add note about duplicate Operator definitions

* PR feedback
  • Loading branch information
sjoerdvisscher authored Feb 4, 2020
1 parent 25f1db6 commit 7572230
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 40 deletions.
1 change: 1 addition & 0 deletions halogen-diagram-editor/src/View/Diagram/Model.purs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type DiagramInfo =
-- must be unique; problematic, want to use lenses instead
type OperatorId = String

-- TODO: merge with Operator in Language.Statebox.Wiring.Generator.DiagramV2.Operators
type Operator =
{ identifier :: OperatorId
, pos :: Vec3 Int
Expand Down
39 changes: 3 additions & 36 deletions stbx-lang/src/Language/Statebox/Wiring/Generator/DiagramV2.purs
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
module Language.Statebox.Wiring.Generator.DiagramV2 where

import Prelude
import Data.Array (zipWith, take, drop, concat, length, (..), (!!), uncons, elemIndex, filter, findIndex)
import Data.Array (zipWith, take, drop, concat, length, (..), (!!), uncons, elemIndex, filter)
import Data.Char (fromCharCode, toCharCode)
import Data.Foldable (class Foldable, maximum, intercalate, foldMap, fold, notElem)
import Data.FoldableWithIndex (foldMapWithIndex)
import Data.FunctorWithIndex (mapWithIndex)
import Data.List (List)
import Data.Map (Map, fromFoldableWith, lookup, union, toUnfoldable)
import Data.Map.Internal (keys)
import Data.Maybe (Maybe, maybe, fromMaybe)
import Data.String.CodeUnits (singleton, charAt)
import Data.Maybe (maybe, fromMaybe)
import Data.String.CodeUnits (singleton)
import Data.TraversableWithIndex (mapAccumLWithIndex)
import Data.Tuple (snd)
import Data.Tuple.Nested ((/\), type (/\))
import Data.Function.Memoize (memoize, class Tabulate)
import Data.Vec3 (Vec3, _x, _y, _z)
import Statebox.Core.Types (Diagram)

import Language.Statebox.Wiring.Generator (Edges, toIndexedGraph, getEdges)
Expand All @@ -41,38 +40,6 @@ fromDiagram { width, pixels, names } = fromEdges (_ - 1) name edges
edges = concat $ zipWith (zipWith (\src tgt -> { src, tgt })) rows (drop 1 rows)
name id = names !! (id - 1) # fromMaybe "?"

type Operator r =
{ label :: String
, pos :: Vec3 Int
| r
}

fromOperators :: r. Array (Operator r) -> DiagramV2
fromOperators ops = fromEdges identity ((ops !! _) >>> maybe "" _.label) edges
where
isConnected srcPos tgtPos
= _y tgtPos == _y srcPos + 1
&& srcStart < tgtEnd
&& tgtStart < srcEnd
where
srcStart = _x srcPos
tgtStart = _x tgtPos
srcEnd = srcStart + _z srcPos
tgtEnd = tgtStart + _z tgtPos
edges =
ops # foldMapWithIndex \src { pos : srcPos } ->
ops # foldMapWithIndex \tgt { pos : tgtPos } ->
if isConnected srcPos tgtPos then [{ src, tgt }] else []

pixel2operator :: r. Array (Operator r) -> String -> Maybe (Operator r)
pixel2operator ops pixelName = do
pixelChar <- charAt 0 pixelName
ops !! (toCharCode pixelChar - toCharCode 'a')

operator2pixel :: r. Array (Operator r) -> (Operator r -> Boolean) -> Maybe String
operator2pixel ops test =
findIndex test ops <#> nextChar 'a'

fromEdges :: a. Ord a => Tabulate a => (a -> Int) -> (a -> String) -> Edges a -> DiagramV2
fromEdges fromEnum name edges = { pixels, context }
where
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
module Language.Statebox.Wiring.Generator.DiagramV2.Operators where

import Prelude
import Data.Array (findIndex, length, replicate, uncons, (!!), null)
import Data.Char (toCharCode)
import Data.Foldable (all, fold, intercalate)
import Data.FoldableWithIndex (foldMapWithIndex)
import Data.FunctorWithIndex (mapWithIndex)
import Data.Maybe (Maybe(..), maybe)
import Data.Monoid (guard)
import Data.String (length) as S
import Data.String.CodeUnits (charAt, splitAt)
import Data.Vec3 (Vec3, _x, _y, _z)

import Language.Statebox.Wiring.Generator.DiagramV2

-- TODO: merge with Operator in View.Diagram.Model
type Operator r =
{ label :: String
, pos :: Vec3 Int
| r
}

fromOperators :: r. Array (Operator r) -> DiagramV2
fromOperators ops =
{ pixels: if null unconnected then pixels else unconnectedPixels <> "\n" <> pixels -- drawPixels ops
, context: context <> "\n" <> unconnectedContext }
where
name i = (ops !! i) # maybe "" _.label
isConnected srcPos tgtPos
= _y tgtPos == _y srcPos + 1
&& srcStart < tgtEnd
&& tgtStart < srcEnd
where
srcStart = _x srcPos
tgtStart = _x tgtPos
srcEnd = srcStart + _z srcPos
tgtEnd = tgtStart + _z tgtPos
edges =
ops # foldMapWithIndex \src { pos: srcPos } ->
ops # foldMapWithIndex \tgt { pos: tgtPos } ->
if isConnected srcPos tgtPos then [{ src, tgt }] else []
{ pixels, context } = fromEdges identity name edges
unconnected = ops # foldMapWithIndex \i _ -> [i] # guard (edges # all (\{ src, tgt } -> src /= i && tgt /= i))
unconnectedPixels = unconnected <#> nextChar 'a' # fold
unconnectedContext = unconnected <#> (\i -> name i <> "@" <> nextChar 'a' i <> ": ->") # intercalate "\n"

fromPixel :: r. Array (Operator r) -> String -> Maybe (Operator r)
fromPixel ops pixelName = do
pixelChar <- charAt 0 pixelName
ops !! (toCharCode pixelChar - toCharCode 'a')

toPixel :: r. Array (Operator r) -> (Operator r -> Boolean) -> Maybe String
toPixel ops test =
findIndex test ops <#> nextChar 'a'

drawPixels :: r. Array (Operator r) -> String
drawPixels ops = drawPixels' ops 0 [] # intercalate "\n"
where
drawPixels' arr i pixels' = case uncons arr of
Nothing -> pixels'
Just { head: { pos }, tail } ->
drawPixels' tail (i + 1) pixels
where
xs = _x pos
xe = xs + _z pos
y = _y pos
pixel = nextChar 'a' i
pad 0 = ""
pad n = " " <> pad (n - 1)
addPixel l = let s = splitAt y l in s.before <> pad (max 0 (y - S.length l)) <> pixel <> s.after

pixels'' :: Array String
pixels'' = pixels' <> replicate (max 0 (xe - length pixels')) ""

pixels :: Array String
pixels = pixels'' # mapWithIndex \x l -> if x >= xs && x < xe then addPixel l else l
4 changes: 2 additions & 2 deletions studio/src/View/Studio.purs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import Halogen.HTML (HTML)
import Halogen.Query.HalogenM (HalogenM)

import Data.Petrinet.Representation.PNPRO as PNPRO
import Language.Statebox.Wiring.Generator.DiagramV2 as DiagramV2
import Language.Statebox.Wiring.Generator.DiagramV2.Operators as DiagramV2
import Statebox.Client as Stbx
import Statebox.Client (evalTransactionResponse)
import Statebox.Core.Transaction as Stbx
Expand Down Expand Up @@ -152,7 +152,7 @@ ui =
let boxes = (KDMonCat.Bricks.toBricksInput (DiagramV2.fromOperators diagramInfo.ops) selBox).selectedBoxes
maybe (pure unit) (handleAction <<< HandleDiagramEditorMsg <<< DiagramEditor.OperatorClicked) $ do
box <- Set.findMin boxes
op <- DiagramV2.pixel2operator diagramInfo.ops box.bid
op <- DiagramV2.fromPixel diagramInfo.ops box.bid
pure op.identifier

HandlePetrinetEditorMsg NetUpdated -> do
Expand Down
4 changes: 2 additions & 2 deletions studio/src/View/Studio/View.purs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import Halogen.HTML.Core (ClassName(..))
import Halogen.HTML.Events (onClick, onValueInput)
import Halogen.HTML.Properties (classes, src, href, placeholder, value)

import Language.Statebox.Wiring.Generator.DiagramV2 (fromOperators, operator2pixel) as DiagramV2
import Language.Statebox.Wiring.Generator.DiagramV2.Operators (fromOperators, toPixel) as DiagramV2
import TreeMenu as TreeMenu
import TreeMenu (mkItem, MenuTree, Item)
import Statebox.Core.Transaction (HashStr, TxSum, evalTxSum, isExecutionTx)
Expand Down Expand Up @@ -105,7 +105,7 @@ contentView apiUrl route = case route of
(KDMonCat.Bricks.defaultRenderBoxContent name bid)
{ className = if maybeSelectedBid == Just bid then "selected" else "" } }
maybeSelectedBid = case nodeMaybe of
Just (NetNode netInfo) -> DiagramV2.operator2pixel diagramInfo.ops (\{ identifier } -> netInfo.name == identifier)
Just (NetNode netInfo) -> DiagramV2.toPixel diagramInfo.ops (\{ identifier } -> netInfo.name == identifier)
_ -> Nothing


Expand Down

0 comments on commit 7572230

Please sign in to comment.