diff --git a/halogen-diagram-editor/src/View/Diagram/Model.purs b/halogen-diagram-editor/src/View/Diagram/Model.purs index d96310a4..4dba5132 100644 --- a/halogen-diagram-editor/src/View/Diagram/Model.purs +++ b/halogen-diagram-editor/src/View/Diagram/Model.purs @@ -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 diff --git a/stbx-lang/src/Language/Statebox/Wiring/Generator/DiagramV2.purs b/stbx-lang/src/Language/Statebox/Wiring/Generator/DiagramV2.purs index 4e81e1fb..1ff2750b 100644 --- a/stbx-lang/src/Language/Statebox/Wiring/Generator/DiagramV2.purs +++ b/stbx-lang/src/Language/Statebox/Wiring/Generator/DiagramV2.purs @@ -1,7 +1,7 @@ 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) @@ -9,13 +9,12 @@ 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) @@ -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 diff --git a/stbx-lang/src/Language/Statebox/Wiring/Generator/DiagramV2/Operators.purs b/stbx-lang/src/Language/Statebox/Wiring/Generator/DiagramV2/Operators.purs new file mode 100644 index 00000000..fb4a32d1 --- /dev/null +++ b/stbx-lang/src/Language/Statebox/Wiring/Generator/DiagramV2/Operators.purs @@ -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 diff --git a/studio/src/View/Studio.purs b/studio/src/View/Studio.purs index 05a53367..ac4e6137 100644 --- a/studio/src/View/Studio.purs +++ b/studio/src/View/Studio.purs @@ -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 @@ -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 diff --git a/studio/src/View/Studio/View.purs b/studio/src/View/Studio/View.purs index 7686fb31..adcc0a43 100644 --- a/studio/src/View/Studio/View.purs +++ b/studio/src/View/Studio/View.purs @@ -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) @@ -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