Commit b083b6c3 authored by Przemyslaw Kaminski's avatar Przemyslaw Kaminski

[Graph] fixes to tree clicking on various graph

I.e. fresh graph loading was fixed (force atlas restarts correctly,
edges are hidden automatically).
parent 3408c4cd
......@@ -4,7 +4,7 @@ module Gargantext.Components.Graph
-- , forceAtlas2Settings, ForceAtlas2Settings, ForceAtlas2OptionalSettings
-- )
where
import Prelude (bind, const, discard, pure, ($), unit, map)
import Prelude (bind, const, discard, pure, ($), unit, map, not, show)
import Data.Array as A
import Data.Either (Either(..))
......@@ -32,6 +32,7 @@ type Props sigma forceatlas2 =
, graph :: SigmaxTypes.SGraph
, multiSelectEnabledRef :: R.Ref Boolean
, selectedNodeIds :: R.State SigmaxTypes.SelectedNodeIds
, showEdges :: R.State SigmaxTypes.ShowEdgesState
, sigmaRef :: R.Ref Sigmax.Sigma
, sigmaSettings :: sigma
, stage :: R.State Stage
......@@ -90,7 +91,7 @@ graphCpt = R.hooksComponent "Graph" cpt
log "[graphCpt] cleanup"
pure $ pure unit
stageHooks props@{sigmaRef, stage: (Ready /\ setStage), transformedGraph} = do
stageHooks props@{showEdges: (showEdges /\ _), sigmaRef, stage: (Ready /\ setStage), transformedGraph} = do
let tEdgesMap = SigmaxTypes.edgesGraphMap transformedGraph
let tNodesMap = SigmaxTypes.nodesGraphMap transformedGraph
......@@ -99,6 +100,7 @@ graphCpt = R.hooksComponent "Graph" cpt
Sigmax.dependOnSigma (R.readRef sigmaRef) "[graphCpt (Ready)] no sigma" $ \sigma -> do
Sigmax.updateEdges sigma tEdgesMap
Sigmax.updateNodes sigma tNodesMap
Sigmax.setEdges sigma (not $ SigmaxTypes.edgeStateHidden showEdges)
stageHooks _ = pure unit
......
......@@ -12,6 +12,7 @@ import Data.Sequence as Seq
import Data.Set as Set
import Data.Tuple (fst, snd, Tuple(..))
import Data.Tuple.Nested ((/\))
import DOM.Simple.Console (log2)
import DOM.Simple.Types (Element)
import Effect.Aff (Aff)
import Math (log)
......@@ -85,12 +86,16 @@ explorerCpt = R.hooksComponent "G.C.GraphExplorer.explorer" cpt
if SigmaxTypes.eqGraph readData graph then
pure unit
else do
-- Graph data changed, reinitialize sigma.
let rSigma = R.readRef controls.sigmaRef
Sigmax.cleanupSigma rSigma "explorerCpt"
R.setRef dataRef graph
-- Reinitialize bunch of state as well.
snd controls.selectedNodeIds $ const Set.empty
snd controls.showEdges $ const SigmaxTypes.EShow
snd controls.forceAtlasState $ const SigmaxTypes.InitialRunning
snd controls.graphStage $ const Graph.Init
snd controls.showSidePanel $ const GET.InitialClosed
pure $
RH.div
......@@ -193,6 +198,7 @@ graphViewCpt = R.hooksComponent "GraphView" cpt
, graph
, multiSelectEnabledRef
, selectedNodeIds: controls.selectedNodeIds
, showEdges: controls.showEdges
, sigmaRef: controls.sigmaRef
, sigmaSettings: Graph.sigmaSettings
, stage: controls.graphStage
......@@ -379,7 +385,7 @@ transformGraph controls graph = SigmaxTypes.Graph {nodes: newNodes, edges: newEd
hasSelection = not $ Set.isEmpty (fst controls.selectedNodeIds)
newNodes = nodeSizeFilter <$> nodeMarked <$> nodes
newEdges = edgeConfluenceFilter <$> edgeWeightFilter <$> edgeMarked <$> edges
newEdges = edgeConfluenceFilter <$> edgeWeightFilter <$> edgeShowFilter <$> edgeMarked <$> edges
nodeSizeFilter node@{ size } =
if Range.within (fst controls.nodeSize) size then
......@@ -392,6 +398,11 @@ transformGraph controls graph = SigmaxTypes.Graph {nodes: newNodes, edges: newEd
edge
else
edge { hidden = true }
edgeShowFilter edge =
if (SigmaxTypes.edgeStateHidden $ fst controls.showEdges) then
edge { hidden = true }
else
edge
edgeWeightFilter edge@{ weight } =
if Range.within (fst controls.edgeWeight) weight then
edge
......
......@@ -14,8 +14,7 @@ import Data.Maybe (Maybe(..), maybe)
import Data.Sequence as Seq
import Data.Set as Set
import Data.Tuple (fst, snd)
import Data.Tuple.Nested ((/\), get1)
import DOM.Simple.Console (log, log2)
import Data.Tuple.Nested ((/\))
import Effect (Effect)
import Effect.Timer (setTimeout)
import Prelude
......@@ -45,6 +44,7 @@ type Controls =
, nodeSize :: R.State Range.NumberRange
, selectedNodeIds :: R.State SigmaxTypes.SelectedNodeIds
, showControls :: R.State Boolean
, showEdges :: R.State SigmaxTypes.ShowEdgesState
, showSidePanel :: R.State GET.SidePanelState
, showTree :: R.State Boolean
, sigmaRef :: R.Ref Sigmax.Sigma
......@@ -55,18 +55,15 @@ controlsToSigmaSettings { cursorSize: (cursorSize /\ _)} = Graph.sigmaSettings
type LocalControls =
( labelSize :: R.State Number
, showEdges :: R.State Boolean
)
initialLocalControls :: R.Hooks (Record LocalControls)
initialLocalControls = do
labelSize <- R.useState' 14.0
search <- R.useState' ""
showEdges <- R.useState' true
pure $ {
labelSize
, showEdges
}
controls :: Record Controls -> R.Element
......@@ -81,20 +78,29 @@ controlsCpt = R.hooksComponent "GraphControls" cpt
-- If user pauses FA before auto is triggered, clear the timeoutId
mFAPauseRef <- R.useRef Nothing
-- when graph is changed, cleanup the mFAPauseRef
-- When graph is changed, cleanup the mFAPauseRef so that forceAtlas
-- timeout is retriggered.
R.useEffect' $ do
case fst props.graphStage of
Graph.Init -> R.setRef mFAPauseRef Nothing
_ -> pure unit
R.useEffect' $ Sigmax.handleForceAtlas2Pause props.sigmaRef props.forceAtlasState (get1 localControls.showEdges) mFAPauseRef
-- Handle case when FA is paused from outside events, eg. the automatic timer.
R.useEffect' $ Sigmax.handleForceAtlas2Pause props.sigmaRef props.forceAtlasState mFAPauseRef
-- Handle automatic edge hiding when FA is running (to prevent flickering).
R.useEffect2' props.sigmaRef props.forceAtlasState $
snd props.showEdges $ SigmaxTypes.forceAtlasEdgeState (fst props.forceAtlasState)
-- Automatic opening of sidebar when a node is selected (but only first time).
R.useEffect' $ do
if fst props.showSidePanel == GET.InitialClosed && (not Set.isEmpty $ fst props.selectedNodeIds) then
snd props.showSidePanel $ \_ -> GET.Opened
else
pure unit
-- Timer to turn off the initial FA. This is because FA eats up lot of
-- CPU, has memory leaks etc.
R.useEffect1' (fst props.forceAtlasState) $ do
if (fst props.forceAtlasState) == SigmaxTypes.InitialRunning then do
timeoutId <- setTimeout 2000 $ do
......@@ -121,7 +127,7 @@ controlsCpt = R.hooksComponent "GraphControls" cpt
[ -- change type button (?)
RH.li {} [ centerButton props.sigmaRef ]
, RH.li {} [ pauseForceAtlasButton {state: props.forceAtlasState} ]
, RH.li {} [ edgesToggleButton props.sigmaRef localControls.showEdges ]
, RH.li {} [ edgesToggleButton {state: props.showEdges} ]
, RH.li {} [ edgeConfluenceControl props.sigmaRef props.edgeConfluence ]
, RH.li {} [ edgeWeightControl props.sigmaRef props.edgeWeight ]
-- change level
......@@ -155,6 +161,7 @@ useGraphControls graph = do
showTree <- R.useState' false
selectedNodeIds <- R.useState' $ Set.empty
showControls <- R.useState' false
showEdges <- R.useState' SigmaxTypes.EShow
showSidePanel <- R.useState' GET.InitialClosed
sigma <- Sigmax.initSigma
sigmaRef <- R.useRef sigma
......@@ -169,6 +176,7 @@ useGraphControls graph = do
, nodeSize
, selectedNodeIds
, showControls
, showEdges
, showSidePanel
, showTree
, sigmaRef
......
......@@ -56,19 +56,28 @@ controlsToggleButton state =
, onClick: \_ -> snd state not
}
edgesToggleButton :: R.Ref Sigmax.Sigma -> R.State Boolean -> R.Element
edgesToggleButton sigmaRef state =
toggleButton {
state: state
, onMessage: "Hide Edges"
, offMessage: "Show Edges"
, onClick: \_ -> do
let sigma = R.readRef sigmaRef
let (toggled /\ setToggled) = state
Sigmax.dependOnSigma sigma "[edgesToggleButton] sigma: Nothing" $ \s -> do
Sigmax.setEdges s $ not toggled
setToggled not
}
type EdgesButtonProps = (
state :: R.State SigmaxTypes.ShowEdgesState
)
edgesToggleButton :: Record EdgesButtonProps -> R.Element
edgesToggleButton props = R.createElement edgesToggleButtonCpt props []
edgesToggleButtonCpt :: R.Component EdgesButtonProps
edgesToggleButtonCpt = R.hooksComponent "EdgesToggleButton" cpt
where
cpt {state: (state /\ setState)} _ = do
pure $
H.span {}
[
H.button
{ className: "btn btn-primary", on: {click: onClick setState} }
[ H.text (text state) ]
]
text s = if SigmaxTypes.edgeStateHidden s then "Show edges" else "Hide edges"
-- TODO: Move this to Graph.purs to the R.useEffect handler which renders nodes/edges
onClick setState _ = setState SigmaxTypes.toggleShowEdgesState
multiSelectEnabledButton :: R.State Boolean -> R.Element
multiSelectEnabledButton state =
......
......@@ -110,8 +110,8 @@ dependOnContainer container notFoundMsg f = do
-- | pausing can be done not only via buttons but also from the initial
-- | setTimer.
--handleForceAtlasPause sigmaRef (toggled /\ setToggled) mFAPauseRef = do
handleForceAtlas2Pause :: R.Ref Sigma -> R.State ST.ForceAtlasState -> Boolean -> R.Ref (Maybe TimeoutId) -> Effect Unit
handleForceAtlas2Pause sigmaRef (toggled /\ setToggled) showEdges mFAPauseRef = do
handleForceAtlas2Pause :: R.Ref Sigma -> R.State ST.ForceAtlasState -> R.Ref (Maybe TimeoutId) -> Effect Unit
handleForceAtlas2Pause sigmaRef (toggled /\ setToggled) mFAPauseRef = do
let sigma = R.readRef sigmaRef
dependOnSigma sigma "[handleForceAtlas2Pause] sigma: Nothing" $ \s -> do
--log2 "[handleForceAtlas2Pause] mSigma: Just " s
......@@ -122,18 +122,15 @@ handleForceAtlas2Pause sigmaRef (toggled /\ setToggled) showEdges mFAPauseRef =
Tuple ST.InitialRunning false -> do
-- hide edges during forceAtlas rendering, this prevents flickering
Sigma.restartForceAtlas2 s
setEdges s false
Tuple ST.Running false -> do
-- hide edges during forceAtlas rendering, this prevents flickering
Sigma.restartForceAtlas2 s
setEdges s false
case R.readRef mFAPauseRef of
Nothing -> pure unit
Just timeoutId -> clearTimeout timeoutId
Tuple ST.Paused true -> do
-- restore edges state
Sigma.stopForceAtlas2 s
setEdges s showEdges
_ -> pure unit
-- handle case when user pressed pause/start fa button before timeout fired
--case R.readRef mFAPauseRef of
......@@ -149,14 +146,16 @@ setEdges sigma val = do
, drawEdgeLabels: val
, hideEdgesOnMove: not val
}
-- prevent showing edges (via show edges button) when FA is running (flickering)
isFARunning <- Sigma.isForceAtlas2Running sigma
case Tuple val isFARunning of
Tuple false _ ->
Sigma.setSettings sigma settings
Tuple true false ->
Sigma.setSettings sigma settings
_ -> pure unit
-- -- prevent showing edges (via show edges button) when FA is running (flickering)
-- isFARunning <- Sigma.isForceAtlas2Running sigma
-- case Tuple val isFARunning of
-- Tuple false _ ->
-- Sigma.setSettings sigma settings
-- Tuple true false ->
-- Sigma.setSettings sigma settings
-- _ -> pure unit
markSelectedEdges :: Sigma.Sigma -> ST.SelectedEdgeIds -> ST.EdgesMap -> Effect Unit
markSelectedEdges sigma selectedEdgeIds graphEdges = do
......@@ -199,7 +198,7 @@ updateEdges sigma edgesMap = do
_ <- pure $ (e .= "color") tColor
_ <- pure $ (e .= "hidden") tHidden
pure unit
Sigma.refresh sigma
--Sigma.refresh sigma
updateNodes :: Sigma.Sigma -> ST.NodesMap -> Effect Unit
......@@ -212,7 +211,7 @@ updateNodes sigma nodesMap = do
_ <- pure $ (n .= "color") tColor
_ <- pure $ (n .= "hidden") tHidden
pure unit
Sigma.refresh sigma
--Sigma.refresh sigma
-- | Toggles item visibility in the selected set
......
module Gargantext.Hooks.Sigmax.Types where
import Prelude (map, ($), (&&), (==), class Ord, Ordering, compare, class Eq)
import Prelude (map, ($), (&&), (==), class Eq, class Ord, class Show, Ordering, compare)
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Eq (genericEq)
import Data.Generic.Rep.Show (genericShow)
import Data.Map as Map
import Data.Sequence (Seq)
import Data.Set as Set
......@@ -65,11 +68,66 @@ eqGraph :: (Graph Node Edge) -> (Graph Node Edge) -> Boolean
eqGraph (Graph {nodes: n1, edges: e1}) (Graph {nodes: n2, edges: e2}) = (n1 == n2) && (e1 == e2)
-- | Custom state for force atlas. Basically, it can be "Running" or "Paused"
-- however when graph is loaded initially, forceAtlas is running for a couple of
-- seconds and then stops (unless the user alters this by clicking the toggle
-- button).
data ForceAtlasState = InitialRunning | Running | Paused
derive instance eqForceAtlasState :: Eq ForceAtlasState
derive instance genericForceAtlasState :: Generic ForceAtlasState _
instance eqForceAtlasState :: Eq ForceAtlasState where
eq = genericEq
toggleForceAtlasState :: ForceAtlasState -> ForceAtlasState
toggleForceAtlasState InitialRunning = Paused
toggleForceAtlasState Running = Paused
toggleForceAtlasState Paused = Running
-- | Custom state for show edges. Normally it is EShow or EHide (show/hide
-- | edges). However, edges are temporarily turned off when forceAtlas is
-- | running.
data ShowEdgesState = EShow | EHide | ETempHiddenThenShow
derive instance genericShowEdgesState :: Generic ShowEdgesState _
instance eqShowEdgesState :: Eq ShowEdgesState where
eq = genericEq
instance showShowEdgesState :: Show ShowEdgesState where
show = genericShow
-- | Whether the edges are hidden now (temp or "stable").
edgeStateHidden :: ShowEdgesState -> Boolean
edgeStateHidden EHide = true
edgeStateHidden ETempHiddenThenShow = true
edgeStateHidden _ = false
-- | Switch from hidden to shown, handling the temp state as well.
toggleShowEdgesState :: ShowEdgesState -> ShowEdgesState
toggleShowEdgesState s =
if edgeStateHidden s then
EShow
else
EHide
-- | Return the temporary hidden state, if applicable.
edgeStateTempHide :: ShowEdgesState -> ShowEdgesState
edgeStateTempHide EHide = EHide
edgeStateTempHide _ = ETempHiddenThenShow
-- | Whether, after disabling the temp state, edges will be shown or hidden.
edgeStateWillBeHidden :: ShowEdgesState -> Boolean
edgeStateWillBeHidden EHide = true
edgeStateWillBeHidden _ = false
-- | Get rid of the temporary transition
edgeStateStabilize :: ShowEdgesState -> ShowEdgesState
edgeStateStabilize ETempHiddenThenShow = EShow
edgeStateStabilize s = s
-- | Return state in which showEdges should be depending on forceAtlasState
forceAtlasEdgeState :: ForceAtlasState -> ShowEdgesState -> ShowEdgesState
forceAtlasEdgeState InitialRunning EShow = ETempHiddenThenShow
forceAtlasEdgeState InitialRunning es = es
forceAtlasEdgeState Running EShow = ETempHiddenThenShow
forceAtlasEdgeState Running es = es
forceAtlasEdgeState Paused ETempHiddenThenShow = EShow
forceAtlasEdgeState Paused es = es
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