Commit 565d20c5 authored by Alexandre Delanoë's avatar Alexandre Delanoë

[MERGE]

parents 1688f15f 9f1d85a7
...@@ -9495,6 +9495,10 @@ input[type=range]:-moz-focusring { ...@@ -9495,6 +9495,10 @@ input[type=range]:-moz-focusring {
margin-bottom: 12px; margin-bottom: 12px;
} }
.graph-selected-nodes__item {
display: inline-block;
padding: 2px;
}
.graph-selected-nodes__item:not(:last-child) { .graph-selected-nodes__item:not(:last-child) {
margin-bottom: 4px; margin-bottom: 4px;
} }
......
...@@ -9448,6 +9448,10 @@ input[type=range]:-moz-focusring { ...@@ -9448,6 +9448,10 @@ input[type=range]:-moz-focusring {
margin-bottom: 12px; margin-bottom: 12px;
} }
.graph-selected-nodes__item {
display: inline-block;
padding: 2px;
}
.graph-selected-nodes__item:not(:last-child) { .graph-selected-nodes__item:not(:last-child) {
margin-bottom: 4px; margin-bottom: 4px;
} }
......
...@@ -9204,6 +9204,10 @@ input[type=range]:-moz-focusring { ...@@ -9204,6 +9204,10 @@ input[type=range]:-moz-focusring {
margin-bottom: 12px; margin-bottom: 12px;
} }
.graph-selected-nodes__item {
display: inline-block;
padding: 2px;
}
.graph-selected-nodes__item:not(:last-child) { .graph-selected-nodes__item:not(:last-child) {
margin-bottom: 4px; margin-bottom: 4px;
} }
......
...@@ -9452,6 +9452,10 @@ input[type=range]:-moz-focusring { ...@@ -9452,6 +9452,10 @@ input[type=range]:-moz-focusring {
margin-bottom: 12px; margin-bottom: 12px;
} }
.graph-selected-nodes__item {
display: inline-block;
padding: 2px;
}
.graph-selected-nodes__item:not(:last-child) { .graph-selected-nodes__item:not(:last-child) {
margin-bottom: 4px; margin-bottom: 4px;
} }
......
...@@ -9453,6 +9453,10 @@ input[type=range]:-moz-focusring { ...@@ -9453,6 +9453,10 @@ input[type=range]:-moz-focusring {
margin-bottom: 12px; margin-bottom: 12px;
} }
.graph-selected-nodes__item {
display: inline-block;
padding: 2px;
}
.graph-selected-nodes__item:not(:last-child) { .graph-selected-nodes__item:not(:last-child) {
margin-bottom: 4px; margin-bottom: 4px;
} }
......
...@@ -39,7 +39,7 @@ newtype Node = Node { ...@@ -39,7 +39,7 @@ newtype Node = Node {
, children :: Array String , children :: Array String
, id_ :: String , id_ :: String
, label :: String , label :: String
, size :: Int , size :: Number
, type_ :: String , type_ :: String
, x :: Number , x :: Number
, y :: Number , y :: Number
......
...@@ -9,7 +9,6 @@ import Data.Int (toNumber) ...@@ -9,7 +9,6 @@ import Data.Int (toNumber)
import Data.Map as Map import Data.Map as Map
import Data.Maybe (Maybe(..), fromJust) import Data.Maybe (Maybe(..), fromJust)
import Data.Nullable (null, Nullable) import Data.Nullable (null, Nullable)
import Data.Number as DN
import Data.Sequence as Seq import Data.Sequence as Seq
import Data.Set as Set import Data.Set as Set
import Data.Tuple (Tuple(..)) import Data.Tuple (Tuple(..))
...@@ -290,7 +289,11 @@ graphViewCpt = R.memo' $ here.component "graphView" cpt where ...@@ -290,7 +289,11 @@ graphViewCpt = R.memo' $ here.component "graphView" cpt where
convert :: GET.GraphData -> Tuple (Maybe GET.MetaData) SigmaxT.SGraph convert :: GET.GraphData -> Tuple (Maybe GET.MetaData) SigmaxT.SGraph
convert (GET.GraphData r) = Tuple r.metaData $ SigmaxT.Graph {nodes, edges} convert (GET.GraphData r) = Tuple r.metaData $ SigmaxT.Graph {nodes, edges}
where where
nodes = foldMapWithIndex nodeFn $ GEU.normalizeNodeSize 1 10000 r.nodes normalizedNodes :: Array GEGT.Node
normalizedNodes = GEGT.Node <$> (GEU.normalizeNodeSizeDefault $ (\(GEGT.Node n) -> n) <$> r.nodes)
nodes :: Seq.Seq (Record SigmaxT.Node)
nodes = foldMapWithIndex nodeFn normalizedNodes
nodeFn :: Int -> GEGT.Node -> Seq.Seq (Record SigmaxT.Node)
nodeFn _i nn@(GEGT.Node n) = nodeFn _i nn@(GEGT.Node n) =
Seq.singleton { Seq.singleton {
borderColor: color borderColor: color
...@@ -302,7 +305,7 @@ convert (GET.GraphData r) = Tuple r.metaData $ SigmaxT.Graph {nodes, edges} ...@@ -302,7 +305,7 @@ convert (GET.GraphData r) = Tuple r.metaData $ SigmaxT.Graph {nodes, edges}
, highlighted: false , highlighted: false
, id : n.id_ , id : n.id_
, label : n.label , label : n.label
, size : DN.log (toNumber n.size + 1.0) , size : n.size
--, size: toNumber n.size --, size: toNumber n.size
, type : modeGraphType gargType , type : modeGraphType gargType
, x : n.x -- cos (toNumber i) , x : n.x -- cos (toNumber i)
...@@ -343,7 +346,8 @@ modeGraphType Types.Authors = "square" ...@@ -343,7 +346,8 @@ modeGraphType Types.Authors = "square"
modeGraphType Types.Institutes = "equilateral" modeGraphType Types.Institutes = "equilateral"
modeGraphType Types.Sources = "star" modeGraphType Types.Sources = "star"
--modeGraphType Types.Terms = "def" --modeGraphType Types.Terms = "def"
modeGraphType Types.Terms = "circle" --modeGraphType Types.Terms = "circle"
modeGraphType Types.Terms = "ccircle"
-------------------------------------------------------------- --------------------------------------------------------------
......
...@@ -509,7 +509,7 @@ neighborhoodCpt = R.memo' $ here.component "neighborhood" cpt where ...@@ -509,7 +509,7 @@ neighborhoodCpt = R.memo' $ here.component "neighborhood" cpt where
[ "text-info", "d-inline" ] $ [ "text-info", "d-inline" ] $
show termCount show termCount
, ,
H.text $ nbsp 1 <> "terms" H.text $ nbsp 1 <> "related terms"
, ,
-- Expand word cloud -- Expand word cloud
B.iconButton B.iconButton
...@@ -643,11 +643,12 @@ updateTermButtonCpt = here.component "updateTermButton" cpt where ...@@ -643,11 +643,12 @@ updateTermButtonCpt = here.component "updateTermButton" cpt where
badgeSize :: Number -> Number -> Number -> String badgeSize :: Number -> Number -> Number -> String
badgeSize minSize maxSize size = badgeSize minSize maxSize size =
let let
minFontSize = 10.0 minFontSize = 7.0
maxFontSize = 24.0 maxFontSize = 28.0
sizeScaled = (size - minSize) / (maxSize - minSize) -- in [0; 1] range sizeScaled = (size - minSize) / (maxSize - minSize) -- in [0; 1] range
scale' = DN.log (sizeScaled + 1.0) / (DN.log 2.0) -- in [0; 1] range --scale' = DN.log (sizeScaled + 1.0) / (DN.log 2.0) -- in [0; 1] range
scale = minFontSize + scale' * (maxFontSize - minFontSize) --scale = minFontSize + scale' * (maxFontSize - minFontSize)
scale = minFontSize + sizeScaled * (maxFontSize - minFontSize)
in in
show scale <> "px" show scale <> "px"
......
...@@ -165,51 +165,54 @@ controlsCpt = R.memo' $ here.component "controls" cpt where ...@@ -165,51 +165,54 @@ controlsCpt = R.memo' $ here.component "controls" cpt where
H.nav H.nav
{ className: "graph-toolbar" } { className: "graph-toolbar" }
[ [
B.wad H.div
[ "flex-shrink-0" ] { className: "flex-shrink-0" }
[ [
B.wad H.div
[ "d-flex" ] { className: "d-flex" }
[ [
-- Actions
B.fieldset
{ className: "graph-toolbar__section"
, titleSlot: H.text "Actions"
}
[
-- resetForceAtlasButton { forceAtlasState, sigmaRef }
pauseForceAtlasButton { state: forceAtlasState }
,
gap
{- ,
cameraButton
{ id: graphId'
, forceAtlasState
, hyperdataGraph: hyperdataGraph'
, reloadForest
, session: session
, sigmaRef: sigmaRef
}
-}
]
,
-- View Settings -- View Settings
B.fieldset B.fieldset
{ className: "graph-toolbar__section" { className: "graph-toolbar__section"
, titleSlot: H.text "View settings" , titleSlot: H.text "View settings"
} }
[ [
B.wad centerButton { forceAtlasState
[ "d-flex", "justify-content-space-between" ] , sigmaRef }
[ ,
B.wad gap
[] ,
[ edgesToggleButton
-- resetForceAtlasButton { forceAtlasState, sigmaRef } { state: showEdges
pauseForceAtlasButton { state: forceAtlasState } , stateAtlas: forceAtlasState
] }
, ,
B.wad gap
[] ,
[ louvainToggleButton { forceAtlasState
centerButton , state: showLouvain }
{ forceAtlasState
, sigmaRef
}
,
gap
,
edgesToggleButton
{ state: showEdges
, stateAtlas: forceAtlasState
}
,
gap
,
louvainToggleButton
{ forceAtlasState
, state: showLouvain
}
]
]
] ]
] ]
, ,
...@@ -223,20 +226,16 @@ controlsCpt = R.memo' $ here.component "controls" cpt where ...@@ -223,20 +226,16 @@ controlsCpt = R.memo' $ here.component "controls" cpt where
} }
[ [
-- zoom: 0 -100 - calculate ratio -- zoom: 0 -100 - calculate ratio
multiSelectEnabledButton multiSelectEnabledButton { forceAtlasState
{ forceAtlasState , state: multiSelectEnabled }
, state: multiSelectEnabled
}
, ,
gap gap
, ,
-- toggle multi node selection -- toggle multi node selection
-- save button -- save button
mouseSelectorSizeSlider mouseSelectorSizeSlider { forceAtlasState
{ forceAtlasState , sigmaRef
, sigmaRef , state: mouseSelectorSize }
, state: mouseSelectorSize
}
] ]
] ]
, ,
...@@ -245,86 +244,71 @@ controlsCpt = R.memo' $ here.component "controls" cpt where ...@@ -245,86 +244,71 @@ controlsCpt = R.memo' $ here.component "controls" cpt where
{ className: intercalate " " { className: intercalate " "
[ "graph-toolbar__section" [ "graph-toolbar__section"
, "graph-toolbar__section--controls" , "graph-toolbar__section--controls"
, "flex-grow-1", "flex-shrink-1" , "flex-grow-1 flex-shrink-1"
] ]
, titleSlot: H.text "Controls" , titleSlot: H.text "Controls"
} }
[ [
B.wad H.div
[ "d-flex", "gap-2" ] { className: "d-flex justify-content-between mb-3" }
[ [
B.wad edgeConfluenceControl
[ "flex-grow-1", "px-2", "mb-2" ] { forceAtlasState
[ , range: edgeConfluenceRange
B.wad , state: edgeConfluence }
[ "d-flex", "justify-content-between", "mb-6" ] {- ,
[ edgeWeightControl
edgeConfluenceControl { forceAtlasState
{ forceAtlasState , range: edgeWeightRange
, range: edgeConfluenceRange , state: edgeWeight }
, state: edgeConfluence -}
}
{- ,
edgeWeightControl
{ forceAtlasState
, range: edgeWeightRange
, state: edgeWeight
}
-}
]
,
B.wad
[ "d-flex", "justify-content-between" ]
[
-- change level
-- file upload
-- run demo
-- search button
-- search topics
labelSizeButton
{ forceAtlasState
, sigmaRef
, state: labelSize
}
]
]
,
B.wad
[ "flex-grow-1", "px-2", "mb-2" ]
[
B.wad
[ "d-flex", "justify-content-between", "mb-6" ]
[
-- labels size: 1-4
nodeSizeControl
{ forceAtlasState
, range: nodeSizeRange
, state: nodeSize
}
]
,
B.wad
[ "d-flex", "justify-content-between" ]
[
-- change level
-- file upload
-- run demo
-- search button
-- search topics
labelRenderedSizeThresholdButton
{ forceAtlasState
, sigmaRef
, state: labelRenderedSizeThreshold
}
-- ,
-- -- labels size: 1-4
-- nodeSizeControl
-- { range: nodeSizeRange
-- , state: nodeSize
-- }
]
]
] ]
,
H.div
{ className: "d-flex justify-content-between" }
[
-- change level
-- file upload
-- run demo
-- search button
-- search topics
labelSizeButton { forceAtlasState
, graph
, sigmaRef
, state: labelSize }
]
,
H.div
{ className: "d-flex justify-content-between" }
[
-- labels size: 1-4
nodeSizeControl
{ forceAtlasState
, range: nodeSizeRange
, state: nodeSize }
]
,
H.div
{ className: "d-flex justify-content-between" }
[
-- change level
-- file upload
-- run demo
-- search button
-- search topics
labelRenderedSizeThresholdButton { forceAtlasState
, sigmaRef
, state: labelRenderedSizeThreshold }
-- ,
-- -- labels size: 1-4
-- nodeSizeControl
-- { range: nodeSizeRange
-- , state: nodeSize }
]
] ]
] ]
......
...@@ -6,6 +6,8 @@ module Gargantext.Components.GraphExplorer.Toolbar.SlideButton ...@@ -6,6 +6,8 @@ module Gargantext.Components.GraphExplorer.Toolbar.SlideButton
, mouseSelectorSizeSlider , mouseSelectorSizeSlider
) where ) where
import Data.Array as A
import Data.Map as Map
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Data.Number as DN import Data.Number as DN
import Prelude import Prelude
...@@ -15,7 +17,10 @@ import Reactix.DOM.HTML as H ...@@ -15,7 +17,10 @@ import Reactix.DOM.HTML as H
import Toestand as T import Toestand as T
import Gargantext.Components.Bootstrap.Types (ComponentStatus(Disabled)) import Gargantext.Components.Bootstrap.Types (ComponentStatus(Disabled))
import Gargantext.Components.GraphExplorer.Types as GET
import Gargantext.Components.GraphExplorer.Utils as GEU
import Gargantext.Hooks.Sigmax as Sigmax import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Hooks.Sigmax.Graphology as Graphology
import Gargantext.Hooks.Sigmax.Sigma as Sigma import Gargantext.Hooks.Sigmax.Sigma as Sigma
import Gargantext.Hooks.Sigmax.Types as SigmaxTypes import Gargantext.Hooks.Sigmax.Types as SigmaxTypes
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
...@@ -68,6 +73,7 @@ sizeButtonCpt = here.component "sizeButton" cpt where ...@@ -68,6 +73,7 @@ sizeButtonCpt = here.component "sizeButton" cpt where
type LabelSizeButtonProps = type LabelSizeButtonProps =
( forceAtlasState :: T.Box SigmaxTypes.ForceAtlasState ( forceAtlasState :: T.Box SigmaxTypes.ForceAtlasState
, graph :: T.Box SigmaxTypes.SGraph
, sigmaRef :: R.Ref Sigmax.Sigma , sigmaRef :: R.Ref Sigmax.Sigma
, state :: T.Box Number) , state :: T.Box Number)
...@@ -76,13 +82,19 @@ labelSizeButton = R2.leaf labelSizeButtonCpt ...@@ -76,13 +82,19 @@ labelSizeButton = R2.leaf labelSizeButtonCpt
labelSizeButtonCpt :: R.Component LabelSizeButtonProps labelSizeButtonCpt :: R.Component LabelSizeButtonProps
labelSizeButtonCpt = here.component "labelSizeButton" cpt labelSizeButtonCpt = here.component "labelSizeButton" cpt
where where
cpt { forceAtlasState, sigmaRef, state} _ = do cpt { forceAtlasState, graph, sigmaRef, state} _ = do
graph' <- T.useLive T.unequal graph
let minLabelSize = 1.0
let maxLabelSize = 30.0
let defaultLabelSize = 14.0
pure $ sizeButton { pure $ sizeButton {
state state
, caption: "Label size" , caption: "Label size"
, forceAtlasState , forceAtlasState
, min: 1.0 , min: minLabelSize
, max: 30.0 , max: maxLabelSize
, onChange: \e -> do , onChange: \e -> do
let sigma = R.readRef sigmaRef let sigma = R.readRef sigmaRef
let newValue' = DN.fromString $ R.unsafeEventValue e let newValue' = DN.fromString $ R.unsafeEventValue e
...@@ -90,11 +102,20 @@ labelSizeButtonCpt = here.component "labelSizeButton" cpt ...@@ -90,11 +102,20 @@ labelSizeButtonCpt = here.component "labelSizeButton" cpt
Nothing -> pure unit Nothing -> pure unit
Just newValue -> Just newValue ->
Sigmax.dependOnSigma sigma "[labelSizeButton] sigma: Nothing" $ \s -> do Sigmax.dependOnSigma sigma "[labelSizeButton] sigma: Nothing" $ \s -> do
let ratio = (newValue - minLabelSize) / (defaultLabelSize - minLabelSize)
let nodes = SigmaxTypes.graphNodes graph'
let nodesResized = (\n@{ size } -> n { size = size * ratio }) <$> nodes
let nodesMap = SigmaxTypes.idMap nodesResized
Graphology.forEachNode (Sigma.graph s) $ \{ id } -> do
case Map.lookup id nodesMap of
Nothing -> pure unit
Just { size } -> Graphology.mergeNodeAttributes (Sigma.graph s) id { size }
Sigma.setSettings s { Sigma.setSettings s {
defaultLabelSize: newValue defaultLabelSize: newValue
, drawLabels: true , drawLabels: true
, labelSize: newValue , labelSize: newValue
, maxNodeSize: newValue / 2.5 -- , maxNodeSize: newValue / 2.5
--, labelSizeRatio: newValue / 2.5 --, labelSizeRatio: newValue / 2.5
} }
T.write_ newValue state T.write_ newValue state
...@@ -145,7 +166,7 @@ mouseSelectorSizeSliderCpt = here.component "mouseSelectorSizeSlider" cpt ...@@ -145,7 +166,7 @@ mouseSelectorSizeSliderCpt = here.component "mouseSelectorSizeSlider" cpt
caption: "Selector size (Shift + wheel)" caption: "Selector size (Shift + wheel)"
, forceAtlasState , forceAtlasState
, min: 1.0 , min: 1.0
, max: 50.0 , max: 100.0
, onChange: \e -> do , onChange: \e -> do
let sigma = R.readRef sigmaRef let sigma = R.readRef sigmaRef
let newValue' = DN.fromString $ R.unsafeEventValue e let newValue' = DN.fromString $ R.unsafeEventValue e
......
module Gargantext.Components.GraphExplorer.Utils module Gargantext.Components.GraphExplorer.Utils
( stEdgeToGET, stNodeToGET ( stEdgeToGET, stNodeToGET
, normalizeNodes , normalizeNodes
, normalizeNodeSizeDefault
, normalizeNodeSize , normalizeNodeSize
, takeGreatestNodeByCluster, countNodeByCluster , takeGreatestNodeByCluster, countNodeByCluster
) where ) where
...@@ -13,6 +14,7 @@ import Data.Lens (Lens', lens, over, traversed, (^.)) ...@@ -13,6 +14,7 @@ import Data.Lens (Lens', lens, over, traversed, (^.))
import Data.Int (floor, toNumber) import Data.Int (floor, toNumber)
import Data.Maybe (Maybe(..), fromMaybe, maybe) import Data.Maybe (Maybe(..), fromMaybe, maybe)
import Data.Newtype (wrap) import Data.Newtype (wrap)
import Data.Number as DN
import Data.Sequence as Seq import Data.Sequence as Seq
import Data.Traversable (class Traversable) import Data.Traversable (class Traversable)
import Gargantext.Components.GraphExplorer.GraphTypes as GEGT import Gargantext.Components.GraphExplorer.GraphTypes as GEGT
...@@ -49,8 +51,16 @@ normalizeNodes ns = GUL.normalizeLens xLens $ GUL.normalizeLens yLens ns ...@@ -49,8 +51,16 @@ normalizeNodes ns = GUL.normalizeLens xLens $ GUL.normalizeLens yLens ns
yLens :: Lens' GEGT.Node Number yLens :: Lens' GEGT.Node Number
yLens = lens (\(GEGT.Node { y }) -> y) $ (\(GEGT.Node n) val -> GEGT.Node (n { y = val })) yLens = lens (\(GEGT.Node { y }) -> y) $ (\(GEGT.Node n) val -> GEGT.Node (n { y = val }))
normalizeNodeSize :: forall t. Traversable t => Int -> Int -> t GEGT.Node -> t GEGT.Node type NodeSize r = { size :: Number | r }
normalizeNodeSize minSize maxSize ns = over traversed (over sizeLens (\s -> toNumber minSize + (s - sizeMin') * quotient)) ns
normalizeNodeSizeDefault :: forall t r. Traversable t => t (NodeSize r) -> t (NodeSize r)
normalizeNodeSizeDefault ns = logSize <$> normalizeNodeSize 50.0 100000.0 ns
where
logSize (n@{ size }) = n { size = DN.log (size + 1.0) }
normalizeNodeSize :: forall t r. Traversable t =>
Number -> Number -> t (NodeSize r) -> t (NodeSize r)
normalizeNodeSize minSize maxSize ns = over traversed (over sizeLens (\s -> minSize + (s - sizeMin') * quotient)) ns
where where
sizes = over traversed (_ ^. sizeLens) ns sizes = over traversed (_ ^. sizeLens) ns
sizeMin = minimum sizes sizeMin = minimum sizes
...@@ -62,9 +72,12 @@ normalizeNodeSize minSize maxSize ns = over traversed (over sizeLens (\s -> toNu ...@@ -62,9 +72,12 @@ normalizeNodeSize minSize maxSize ns = over traversed (over sizeLens (\s -> toNu
sizeMin' = fromMaybe 0.0 sizeMin sizeMin' = fromMaybe 0.0 sizeMin
divisor = maybe 1.0 (\r -> 1.0 / r) range divisor = maybe 1.0 (\r -> 1.0 / r) range
quotient :: Number quotient :: Number
quotient = (toNumber $ maxSize - minSize) * divisor quotient = (maxSize - minSize) * divisor
sizeLens :: Lens' GEGT.Node Number --quotient = (toNumber $ maxSize - minSize) * divisor
sizeLens = lens (\(GEGT.Node { size }) -> toNumber size) $ (\(GEGT.Node n) val -> GEGT.Node (n { size = floor val })) --sizeLens :: Lens' GEGT.Node Number
--sizeLens = lens (\(GEGT.Node { size }) -> size) $ (\(GEGT.Node n) val -> GEGT.Node (n { size = val }))
sizeLens :: Lens' { size :: Number | r } Number
sizeLens = lens (\{ size } -> size) $ \n val -> (n { size = val })
------------------------------------------------------------------------ ------------------------------------------------------------------------
......
...@@ -98,22 +98,22 @@ nodeCpt = here.component "node" cpt where ...@@ -98,22 +98,22 @@ nodeCpt = here.component "node" cpt where
Tuple mMetaData graph = convert hyperdataGraph Tuple mMetaData graph = convert hyperdataGraph
in in
hydrateStore hydrateStore
{ graph { cacheParams: cache'
, graph
, graphId
, hyperdataGraph: loaded , hyperdataGraph: loaded
, mMetaData , mMetaData
, graphId
, cacheParams: cache'
} }
} }
-------------------------------------------------------- --------------------------------------------------------
type HydrateStoreProps = type HydrateStoreProps =
( mMetaData :: Maybe GET.MetaData ( cacheParams :: GET.CacheParams
, graph :: SigmaxT.SGraph , graph :: SigmaxT.SGraph
, hyperdataGraph :: GET.HyperdataGraph
, graphId :: GET.GraphId , graphId :: GET.GraphId
, cacheParams :: GET.CacheParams , hyperdataGraph :: GET.HyperdataGraph
, mMetaData :: Maybe GET.MetaData
) )
hydrateStore :: R2.Leaf HydrateStoreProps hydrateStore :: R2.Leaf HydrateStoreProps
......
...@@ -18,6 +18,13 @@ export function _mergeNodeAttributes(g, name, attrs) { ...@@ -18,6 +18,13 @@ export function _mergeNodeAttributes(g, name, attrs) {
return g.mergeNodeAttributes(name, attrs); return g.mergeNodeAttributes(name, attrs);
} }
export function _forEachNode(g, fn) {
return g.forEachNode(function(_name, attrs) {
// NOTE: fn is an effectful function, it wraps `do` in a separate function
return fn(attrs)();
})
}
export function _addEdge(g, source, target, e) { export function _addEdge(g, source, target, e) {
//return g.addEdge(source, target, e); //return g.addEdge(source, target, e);
......
...@@ -27,6 +27,7 @@ foreign import _addNode :: EffectFn3 Graph String (Record Types.Node) String ...@@ -27,6 +27,7 @@ foreign import _addNode :: EffectFn3 Graph String (Record Types.Node) String
foreign import _updateNode :: EffectFn3 Graph String (Record Types.Node -> Record Types.Node) Unit foreign import _updateNode :: EffectFn3 Graph String (Record Types.Node -> Record Types.Node) Unit
foreign import _addEdge :: EffectFn4 Graph String String (Record Types.Edge) String foreign import _addEdge :: EffectFn4 Graph String String (Record Types.Edge) String
foreign import _mergeNodeAttributes :: forall a. EffectFn3 Graph String a Unit foreign import _mergeNodeAttributes :: forall a. EffectFn3 Graph String a Unit
foreign import _forEachNode :: EffectFn2 Graph (Record Types.Node -> Effect Unit) Unit
--foreign import _updateEdge :: EffectFn4 Graph String String (Record Types.Edge) String --foreign import _updateEdge :: EffectFn4 Graph String String (Record Types.Edge) String
foreign import _mapNodes :: forall a. Fn2 Graph (Record Types.Node -> a) (Array a) foreign import _mapNodes :: forall a. Fn2 Graph (Record Types.Node -> a) (Array a)
foreign import _filterNodes :: Fn2 Graph (Record Types.Node -> Boolean) (Array Types.NodeId) foreign import _filterNodes :: Fn2 Graph (Record Types.Node -> Boolean) (Array Types.NodeId)
...@@ -65,9 +66,7 @@ updateNode g node@{ id, borderColor, color, equilateral, hidden, highlighted, ty ...@@ -65,9 +66,7 @@ updateNode g node@{ id, borderColor, color, equilateral, hidden, highlighted, ty
mergeNodeAttributes :: forall a. Graph -> Types.NodeId -> a -> Effect Unit mergeNodeAttributes :: forall a. Graph -> Types.NodeId -> a -> Effect Unit
mergeNodeAttributes = runEffectFn3 _mergeNodeAttributes mergeNodeAttributes = runEffectFn3 _mergeNodeAttributes
forEachNode :: Graph -> (Record Types.Node -> Effect Unit) -> Effect Unit forEachNode :: Graph -> (Record Types.Node -> Effect Unit) -> Effect Unit
-- TODO Check this: how does FFI translate function of two arguments forEachNode = runEffectFn2 _forEachNode
-- into PS \x y ?
forEachNode g fn = pure $ g ... "forEachNode" $ [\_ n -> fn n]
mapNodes :: forall a. Graph -> (Record Types.Node -> a) -> Array a mapNodes :: forall a. Graph -> (Record Types.Node -> a) -> Array a
mapNodes = runFn2 _mapNodes mapNodes = runFn2 _mapNodes
filterNodes :: Graph -> (Record Types.Node -> Boolean) -> Array Types.NodeId filterNodes :: Graph -> (Record Types.Node -> Boolean) -> Array Types.NodeId
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
import Graph from 'graphology'; import Graph from 'graphology';
import Sigma from 'sigma'; import Sigma from 'sigma';
import { takeScreenshot } from '../../src/external-deps/sigmajs-screenshot.js'; import { takeScreenshot } from '../../src/external-deps/sigmajs-screenshot.js';
import CircleNodeProgram from 'sigma/rendering/webgl/programs/node.fast';
import ContourCircleNodeProgram from '../../src/external-deps/sigmajs-circle-with-contour.js';
let sigma = Sigma.Sigma; let sigma = Sigma.Sigma;
console.log('imported sigma', Sigma); console.log('imported sigma', Sigma);
...@@ -164,7 +166,14 @@ let sigmaMouseSelector = function(sigma, options) { ...@@ -164,7 +166,14 @@ let sigmaMouseSelector = function(sigma, options) {
function _sigma(left, right, el, opts) { function _sigma(left, right, el, opts) {
try { try {
let graph = new Graph(); let graph = new Graph();
let s = new sigma(graph, el, opts.settigns); const settings = {
nodeProgramClasses: {
circle: CircleNodeProgram.default, // TODO why default? It seems that import should be fixed
ccircle: ContourCircleNodeProgram
},
...opts.settings
};
let s = new sigma(graph, el, settings);
console.log('[_sigma] initializing sigma with el', el, 'opts', opts.settings, 'sigma', s); console.log('[_sigma] initializing sigma with el', el, 'opts', opts.settings, 'sigma', s);
console.log('[_sigma] labelRenderedSizeThreshold', opts.settings.labelRenderedSizeThreshold); console.log('[_sigma] labelRenderedSizeThreshold', opts.settings.labelRenderedSizeThreshold);
sigmaMouseSelector(s); sigmaMouseSelector(s);
......
...@@ -9,6 +9,7 @@ import Data.Map as Map ...@@ -9,6 +9,7 @@ import Data.Map as Map
import Data.Maybe (Maybe(..), fromJust) import Data.Maybe (Maybe(..), fromJust)
import Data.Sequence as Seq import Data.Sequence as Seq
import Data.Set as Set import Data.Set as Set
import Data.Traversable (class Traversable)
import Data.Tuple (Tuple(..)) import Data.Tuple (Tuple(..))
import Partial.Unsafe (unsafePartial) import Partial.Unsafe (unsafePartial)
import Prelude (class Eq, class Show, map, ($), (&&), (==), (||), (<$>), (<), mod, not) import Prelude (class Eq, class Show, map, ($), (&&), (==), (||), (<$>), (<), mod, not)
...@@ -107,19 +108,20 @@ graphEdges (Graph {edges}) = edges ...@@ -107,19 +108,20 @@ graphEdges (Graph {edges}) = edges
graphNodes :: SGraph -> Seq.Seq (Record Node) graphNodes :: SGraph -> Seq.Seq (Record Node)
graphNodes (Graph {nodes}) = nodes graphNodes (Graph {nodes}) = nodes
idMap :: forall r t. Traversable t => t { id :: String | r } -> Map.Map String { id :: String | r }
idMap xs = Map.fromFoldable $ (\x@{ id } -> Tuple id x) <$> xs
edgesGraphMap :: SGraph -> EdgesMap edgesGraphMap :: SGraph -> EdgesMap
edgesGraphMap graph = edgesGraphMap graph = idMap $ graphEdges graph
Map.fromFoldable $ map (\e -> Tuple e.id e) $ graphEdges graph
edgesFilter :: (Record Edge -> Boolean) -> SGraph -> SGraph edgesFilter :: (Record Edge -> Boolean) -> SGraph -> SGraph
edgesFilter f (Graph {edges, nodes}) = Graph { edges: Seq.filter f edges, nodes } edgesFilter f (Graph {edges, nodes}) = Graph { edges: Seq.filter f edges, nodes }
nodesMap :: Seq.Seq (Record Node) -> NodesMap nodesMap :: Seq.Seq (Record Node) -> NodesMap
nodesMap nodes = Map.fromFoldable $ map (\n -> Tuple n.id n) nodes nodesMap = idMap
nodesGraphMap :: SGraph -> NodesMap nodesGraphMap :: SGraph -> NodesMap
nodesGraphMap graph = nodesGraphMap graph = idMap $ graphNodes graph
nodesMap $ graphNodes graph
nodesFilter :: (Record Node -> Boolean) -> SGraph -> SGraph nodesFilter :: (Record Node -> Boolean) -> SGraph -> SGraph
nodesFilter f (Graph {edges, nodes}) = Graph { edges, nodes: Seq.filter f nodes } nodesFilter f (Graph {edges, nodes}) = Graph { edges, nodes: Seq.filter f nodes }
......
// Based on sigma.js/src/rendering/webgl/programs/node.fast.ts
import { NodeDisplayData } from "sigma/types";
import { floatColor } from "sigma/utils";
import vertexShaderSource from "sigma/rendering/webgl/shaders/node.fast.vert.glsl";
import fragmentShaderSource from "sigma/rendering/webgl/shaders/node.fast.frag.glsl";
import { AbstractNodeProgram } from "sigma/rendering/webgl/programs/common/node";
import { RenderParams } from "sigma/rendering/webgl/programs/common/program";
import CircleNodeProgram from 'sigma/rendering/webgl/programs/node.fast';
const POINTS = 2;
const ATTRIBUTES = 4;
/*
export default class NodeContourFastProgram extends AbstractNodeProgram {
//constructor(gl : WebGLRenderingContext) {
constructor(gl) {
super(gl, vertexShaderSource, fragmentShaderSource, POINTS, ATTRIBUTES);
this.bind();
}
*/
export default class NodeContourFastProgram extends CircleNodeProgram {
//process(data: NodeDisplayData, hidden: boolean, offset: number): void {
process(data, hidden, offset) {
const array = this.array;
let i = offset * POINTS * ATTRIBUTES;
if (hidden) {
// contour
array[i++] = 0;
array[i++] = 0;
array[i++] = 0;
array[i++] = 0;
// circle
array[i++] = 0;
array[i++] = 0;
array[i++] = 0;
array[i++] = 0;
return;
}
const color = floatColor(data.color);
const black = floatColor('black');
// contour
array[i++] = data.x;
array[i++] = data.y;
array[i++] = data.size + 1;
array[i++] = black;
// circle
array[i++] = data.x;
array[i++] = data.y;
array[i++] = data.size;
array[i] = color;
}
//render(params: RenderParams): void {
render(params) {
if (this.hasNothingToRender()) return;
const gl = this.gl;
const program = this.program;
gl.useProgram(program);
gl.uniform1f(this.ratioLocation, 1 / Math.sqrt(params.ratio));
gl.uniform1f(this.scaleLocation, params.scalingRatio);
gl.uniformMatrix3fv(this.matrixLocation, false, params.matrix);
gl.drawArrays(gl.POINTS, 0, this.array.length / ATTRIBUTES);
}
}
...@@ -216,6 +216,9 @@ ...@@ -216,6 +216,9 @@
&__item &__item
display: inline-block
padding: 2px
&:not(:last-child) &:not(:last-child)
margin-bottom: space-x(0.5) margin-bottom: space-x(0.5)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment