Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
purescript-gargantext
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Grégoire Locqueville
purescript-gargantext
Commits
2fa0f2d8
Commit
2fa0f2d8
authored
Sep 28, 2022
by
Przemyslaw Kaminski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[sigma] mouse clicking works now
Hover still doesn't though.
parent
faf6c03f
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
92 additions
and
123 deletions
+92
-123
FacetsTable.purs
src/Gargantext/Components/FacetsTable.purs
+1
-1
Layout.purs
src/Gargantext/Components/GraphExplorer/Layout.purs
+3
-2
Resources.purs
src/Gargantext/Components/GraphExplorer/Resources.purs
+6
-4
DocList.purs
src/Gargantext/Components/GraphExplorer/Sidebar/DocList.purs
+2
-2
SlideButton.purs
...gantext/Components/GraphExplorer/Toolbar/SlideButton.purs
+1
-3
Sigmax.purs
src/Gargantext/Hooks/Sigmax.purs
+19
-22
Sigma.js
src/Gargantext/Hooks/Sigmax/Sigma.js
+42
-89
Sigma.purs
src/Gargantext/Hooks/Sigmax/Sigma.purs
+8
-0
Types.purs
src/Gargantext/Hooks/Sigmax/Types.purs
+1
-0
Set.purs
src/Gargantext/Utils/Set.purs
+9
-0
No files found.
src/Gargantext/Components/FacetsTable.purs
View file @
2fa0f2d8
...
...
@@ -227,7 +227,7 @@ loadPage { session, nodeId, listId, query, params: {limit, offset, orderBy } } =
case eSearchResult of
Left err -> pure $ Left err
Right (SearchResult {result}) -> do
liftEffect $ here.log2 "[loadPage] result" result
--
liftEffect $ here.log2 "[loadPage] result" result
-- $ SearchQuery {query: concat query, expected: SearchDoc}
pure $ Right $ case result of
SearchResultDoc {docs} -> Docs {docs: doc2view <$> Seq.fromFoldable docs}
...
...
src/Gargantext/Components/GraphExplorer/Layout.purs
View file @
2fa0f2d8
...
...
@@ -292,6 +292,7 @@ convert (GET.GraphData r) = Tuple r.metaData $ SigmaxT.Graph {nodes, edges}
, equilateral: { numPoints: 3 }
, gargType
, hidden : false
, highlighted: false
, id : n.id_
, label : n.label
, size : DN.log (toNumber n.size + 1.0)
...
...
@@ -406,9 +407,9 @@ transformGraph graph { edgeConfluence'
nodeMarked :: Record SigmaxT.Node -> Record SigmaxT.Node
nodeMarked node@{ id } =
if Set.member id selectedNodeIds' then
node { borderColor = "#000", type = "selected" }
node { borderColor = "#000",
highlighted = true,
type = "selected" }
else
node
node
{ highlighted = false }
nodeHideSize :: Record SigmaxT.Node -> Record SigmaxT.Node
nodeHideSize node@{ size } =
...
...
src/Gargantext/Components/GraphExplorer/Resources.purs
View file @
2fa0f2d8
...
...
@@ -59,12 +59,13 @@ drawGraphCpt = R.memo' $ here.component "graph" cpt where
boxes <- AppStore.use
{ showEdges
, graphStage
, graph
, startForceAtlas
, selectedNodeIds
, multiSelectEnabled
, graphStage
, hyperdataGraph
, mouseSelectorSize
, multiSelectEnabled
, selectedNodeIds
, startForceAtlas
} <- GraphStore.use
showEdges' <- R2.useLive' showEdges
...
...
@@ -125,6 +126,7 @@ drawGraphCpt = R.memo' $ here.component "graph" cpt where
Sigmax.dependOnSigma (R.readRef sigmaRef) "[graphCpt (Ready)] no sigma" $ \sigma -> do
-- bind the click event only initially, when ref was empty
Sigmax.bindSelectedNodesClick sigma selectedNodeIds multiSelectEnabled
Sigmax.bindShiftWheel sigma mouseSelectorSize
_ <- Sigma.bindMouseSelectorPlugin sigma
pure unit
...
...
src/Gargantext/Components/GraphExplorer/Sidebar/DocList.purs
View file @
2fa0f2d8
...
...
@@ -80,8 +80,8 @@ docListWrapperCpt = here.component "wrapper" cpt where
-- | Hooks
-- |
R.useEffect1' selectedNodeIds' $
T.write_ (
selectedNodeIds' # toSearchQuery >>> Just
) query
R.useEffect1' selectedNodeIds' $
do
T.write_ (
Just $ toSearchQuery selectedNodeIds'
) query
-- | Render
-- |
...
...
src/Gargantext/Components/GraphExplorer/Toolbar/SlideButton.purs
View file @
2fa0f2d8
...
...
@@ -85,7 +85,7 @@ mouseSelectorSizeButton :: R.Ref Sigmax.Sigma -> T.Box Number -> R.Element
mouseSelectorSizeButton sigmaRef state =
sizeButton {
state
, caption: "Selector size"
, caption: "Selector size
(Shift + wheel)
"
, min: 1.0
, max: 50.0
, onChange: \e -> do
...
...
@@ -98,7 +98,5 @@ mouseSelectorSizeButton sigmaRef state =
Sigma.setSettings s {
mouseSelectorSize: newValue
}
here.log "[mouseSelectorSizeButton] write start"
T.write_ newValue state
here.log "[mouseSelectorSizeButton] write stop"
}
src/Gargantext/Hooks/Sigmax.purs
View file @
2fa0f2d8
...
...
@@ -24,7 +24,8 @@ import Gargantext.Hooks.Sigmax.Sigma as Sigma
import Gargantext.Hooks.Sigmax.Types as ST
import Gargantext.Utils.Console as C
import Gargantext.Utils.Reactix as R2
import Prelude (Unit, bind, discard, flip, map, not, pure, unit, ($), (&&), (*>), (<<<), (<>), (>>=))
import Gargantext.Utils.Set as GSet
import Prelude (Unit, bind, discard, flip, map, not, pure, unit, ($), (&&), (*>), (<<<), (<>), (>>=), (+), (>), negate)
import Reactix as R
import Toestand as T
...
...
@@ -184,20 +185,15 @@ updateNodes sigma nodesMap = do
-- | Toggles item visibility in the selected set
-- Basically: add items that are NOT in `selected` and remove items
-- that are in `selected`.
multiSelectUpdate :: ST.NodeIds -> ST.NodeIds -> ST.NodeIds
multiSelectUpdate new selected = foldl fld selected new
where
fld selectedAcc item =
if Set.member item selectedAcc then
Set.delete item selectedAcc
else
Set.insert item selectedAcc
multiSelectUpdate new selected = foldl GSet.toggle selected new
bindSelectedNodesClick :: Sigma.Sigma -> T.Box ST.NodeIds -> T.Box Boolean -> Effect Unit
bindSelectedNodesClick sigma selectedNodeIds multiSelectEnabled =
Sigma.bindClickNodes sigma $ \nodeIds' -> do
console.log2 "[bindSelectedNodesClick] nodeIds'" nodeIds'
let nodeIds = Set.fromFoldable nodeIds'
multiSelectEnabled' <- T.read multiSelectEnabled
if multiSelectEnabled' then
...
...
@@ -205,15 +201,16 @@ bindSelectedNodesClick sigma selectedNodeIds multiSelectEnabled =
else
T.write_ nodeIds selectedNodeIds
bindSelectedEdgesClick :: R.Ref Sigma -> R.State ST.EdgeIds -> Effect Unit
bindSelectedEdgesClick sigmaRef (_ /\ setEdgeIds) =
dependOnSigma (R.readRef sigmaRef) "[graphCpt] no sigma" $ \sigma -> do
Sigma.bindClickEdge sigma $ \edge -> do
setEdgeIds \eids ->
if Set.member edge.id eids then
Set.delete edge.id eids
else
Set.insert edge.id eids
bindShiftWheel :: Sigma.Sigma -> T.Box Number -> Effect Unit
bindShiftWheel sigma mouseSelectorSize =
Sigma.bindShiftWheel sigma $ \delta -> do
let step = if delta > 0.0 then 5.0 else -5.0
val <- T.read mouseSelectorSize
let newVal = val + step
Sigma.setSettings sigma {
mouseSelectorSize: newVal
}
T.write_ newVal mouseSelectorSize
selectorWithSize :: Sigma.Sigma -> Int -> Effect Unit
selectorWithSize _ _ = do
...
...
@@ -224,10 +221,10 @@ performDiff sigma g = do
-- if (Seq.null addEdges) && (Seq.null addNodes) && (Set.isEmpty removeEdges) && (Set.isEmpty removeNodes) then
-- pure unit
-- else do
console.log2 "[performDiff] addNodes" addNodes
console.log2 "[performDiff] addEdges" $ A.fromFoldable addEdges
console.log2 "[performDiff] removeNodes" removeNodes
console.log2 "[performDiff] removeEdges" removeEdges
--
console.log2 "[performDiff] addNodes" addNodes
--
console.log2 "[performDiff] addEdges" $ A.fromFoldable addEdges
--
console.log2 "[performDiff] removeNodes" removeNodes
--
console.log2 "[performDiff] removeEdges" removeEdges
traverse_ (Graphology.addNode sigmaGraph) addNodes
traverse_ (Graphology.addEdge sigmaGraph) addEdges
traverse_ (Graphology.removeEdge sigmaGraph) removeEdges
...
...
src/Gargantext/Hooks/Sigmax/Sigma.js
View file @
2fa0f2d8
...
...
@@ -63,73 +63,55 @@ let sigmaMouseSelector = function(sigma, options) {
const
distance
=
(
x1
,
y1
,
x2
,
y2
)
=>
Math
.
sqrt
(
Math
.
pow
(
x1
-
x2
,
2
)
+
Math
.
pow
(
y1
-
y2
,
2
));
let
mouseSelector
=
()
=>
{
let
_self
=
this
;
let
_offset
=
null
;
const
_self
=
this
;
const
_s
=
sigma
;
//const _renderer = renderer;
const
captor
=
sigma
.
mouseCaptor
;
const
_container
=
captor
.
container
;
//renderer.initDOM('canvas', 'mouseSelector');
// A hack to force resize to be called (there is a width/height equality
// check which can't be escaped in any other way).
//renderer.resize(renderer.width - 1, renderer.height - 1);
//renderer.resize(renderer.width + 1, renderer.height + 1);
//const _context = _renderer.contexts.mouseSelector;
const
_context
=
_container
.
getContext
(
'2d'
);
// These are used to prevent using the 'click' event when in fact this was a drag
let
_clickPositionX
=
null
;
let
_clickPositionY
=
null
;
let
_isValidClick
=
false
;
_container
.
onmousemove
=
(
e
)
=>
{
return
mouseMove
(
e
);
};
_container
.
onclick
=
(
e
)
=>
{
return
onClick
(
e
);
};
//_context.canvas.onclick = function(e) { return onClick(e); };
_container
.
onmousedown
=
(
e
)
=>
{
return
onMouseDown
(
e
);
}
_container
.
onmouseup
=
(
e
)
=>
{
return
onMouseUp
(
e
);
}
captor
.
on
(
'click'
,
(
e
)
=>
{
return
onClick
(
e
);
});
// The mouseSelector canvas will pass its events down to the "mouse" canvas.
//_context.canvas.style.pointerEvents = 'none';
sigma
.
on
(
'kill'
,
()
=>
_self
.
unbindAll
());
this
.
unbindAll
=
()
=>
{
// console.log('[sigmaMouseSelector] unbinding');
_container
.
onclick
=
null
;
//_context.canvas.onmousemove = null;
_container
.
onmousemove
=
null
;
_container
.
onmousedown
=
null
;
_container
.
onmouseup
=
null
;
const
unbindAll
=
()
=>
{
// TODO Maybe not needed if sigma is killed and we did bind to
// mouse captor instead of the canvas?
// _container.onclick = null;
// _container.onmousemove = null;
// _container.onmousedown = null;
// _container.onmouseup = null;
}
const
onMouseDown
=
(
e
)
=>
{
_clickPositionX
=
e
.
clientX
;
_clickPositionY
=
e
.
clientY
;
const
bindAll
=
()
=>
{
captor
.
on
(
'mousemove'
,
mouseMove
);
captor
.
on
(
'click'
,
onClick
);
captor
.
on
(
'wheel'
,
onWheel
);
sigma
.
on
(
'kill'
,
()
=>
unbindAll
());
}
const
onMouseUp
=
(
e
)
=>
{
// Prevent triggering click when in fact this was a drag
if
((
_clickPositionX
!=
e
.
clientX
)
||
(
_clickPositionY
!=
e
.
clientY
))
{
_clickPositionX
=
null
;
_clickPositionY
=
null
;
_isValidClick
=
false
;
}
else
{
_isValidClick
=
true
;
const
onWheel
=
(
e
)
=>
{
const
shiftPressed
=
e
.
original
.
shiftKey
;
// zoom in has e.delta > 0 (around 0.44)
// zoom out has e.delta < 0 (around -0.44)
if
(
shiftPressed
)
{
// TODO Fix this so that the canvas is not zoomed.
console
.
log
(
'[onWheel] e'
,
e
);
e
.
original
.
preventDefault
();
e
.
original
.
stopPropagation
();
sigma
.
emit
(
'shiftWheel'
,
{
delta
:
e
.
delta
});
}
}
// Responsible for rendering the selector properly
const
mouseMove
=
(
e
)
=>
{
const
size
=
sigma
.
settings
[
'mouseSelectorSize'
]
||
3
;
//const x = e.clientX + document.body.scrollLeft - _offset.left - size/2;
//const y = e.clientY + document.body.scrollTop - _offset.top - size/2;
const
x
=
e
.
layerX
;
const
y
=
e
.
layerY
;
_context
.
clearRect
(
0
,
0
,
_context
.
canvas
.
width
,
_context
.
canvas
.
height
);
_context
.
fillStyle
=
'rgba(91, 192, 222, 0.7)'
;
_context
.
beginPath
();
_context
.
arc
(
x
,
y
,
e
.
x
,
e
.
y
,
size
,
0
,
Math
.
PI
*
2
,
...
...
@@ -140,61 +122,33 @@ let sigmaMouseSelector = function(sigma, options) {
}
const
onClick
=
(
e
)
=>
{
// TODO For some reason this event is sent again, with
// _clickPositionX/Y empty
if
(
!
_isValidClick
||
!
_clickPositionX
||
!
_clickPositionY
)
{
return
;
}
const
size
=
sigma
.
settings
[
'mouseSelectorSize'
]
||
3
;
//const x = e.data.clientX + document.body.scrollLeft - _offset.left - size/2;
//const y = e.data.clientY + document.body.scrollTop - _offset.top - size/2;
//const prefix = _renderer.options.prefix;
//console.log('[sigmaMouseSelector] clicked', e, x, y, size);
let
nodeIds
=
[];
for
(
let
nodeId
in
sigma
.
nodeDataCache
)
{
let
data
=
sigma
.
nodeDataCache
[
nodeId
];
let
position
=
sigma
.
framedGraphToViewport
(
data
);
// TODO Either distance or node is clicked directly
if
(
distance
(
e
.
x
,
e
.
y
,
position
.
x
,
position
.
y
)
<=
size
)
{
nodeIds
.
push
(
nodeId
);
}
}
/*
sigma.graph.forEachNode((node, attrs) => {
if(distance(x, y, attrs.x, attrs.y) <= size) {
nodes.push(node);
}
});
*/
//console.log('[sigmaMouseSelector] nodes', nodes);
// nodes.forEach((n) => {
// sigma.emit('clickNode', { node: n });
// })
// handle node click when our selector doesn't cover it's center
// (e.g. large nodes)
const
nodeAtPosition
=
sigma
.
getNodeAtPosition
(
e
);
if
((
nodeAtPosition
&&
(
nodeIds
.
indexOf
(
nodeAtPosition
)
==
-
1
)))
{
nodeIds
.
push
(
nodeAtPosition
);
}
sigma
.
emit
(
'clickNodes'
,
{
nodeIds
:
nodeIds
//captor: e.data
})
_clickPositionX
=
null
;
_clickPositionY
=
null
;
return
false
;
}
const
calculateOffset
=
(
element
)
=>
{
var
style
=
window
.
getComputedStyle
(
element
);
var
getCssProperty
=
function
(
prop
)
{
return
parseInt
(
style
.
getPropertyValue
(
prop
).
replace
(
'px'
,
''
))
||
0
;
};
return
{
left
:
element
.
getBoundingClientRect
().
left
+
getCssProperty
(
'padding-left'
),
top
:
element
.
getBoundingClientRect
().
top
+
getCssProperty
(
'padding-top'
)
};
};
// Container resize event listener
// @TODO: debounce?
const
onContainerResize
=
(
entries
)
=>
{
_offset
=
calculateOffset
(
_container
);
};
const
_resizeObserver
=
new
ResizeObserver
(
onContainerResize
);
_resizeObserver
.
observe
(
_container
);
bindAll
();
}
mouseSelector
();
...
...
@@ -209,9 +163,8 @@ let sigmaMouseSelector = function(sigma, options) {
function
_sigma
(
left
,
right
,
el
,
opts
)
{
try
{
let
graph
=
new
Graph
();
console
.
log
(
'initializing sigma with el'
,
el
);
console
.
log
(
'initializing sigma with opts'
,
opts
);
let
s
=
new
sigma
(
graph
,
el
,
opts
);
console
.
log
(
'initializing sigma with el'
,
el
,
'opts'
,
'sigma'
,
s
);
sigmaMouseSelector
(
s
);
return
right
(
s
);
}
catch
(
e
)
{
...
...
src/Gargantext/Hooks/Sigmax/Sigma.purs
View file @
2fa0f2d8
...
...
@@ -137,6 +137,14 @@ bindClickNodes s f = on_ s "clickNodes" $ \e -> do
unbindClickNodes :: Sigma -> Effect Unit
unbindClickNodes s = unbind_ s "clickNodes"
-- | Shift + mousewheel changes selector size
bindShiftWheel :: Sigma -> (Number -> Effect Unit) -> Effect Unit
bindShiftWheel s f = on_ s "shiftWheel" $ \e -> do
let delta = e .. "delta" :: Number
f delta
unbindShiftWheel :: Sigma -> Effect Unit
unbindShiftWheel s = unbind_ s "shiftWheel"
-- | Bind a `overNode` event.
bindOverNode :: Sigma -> (Record Types.Node -> Effect Unit) -> Effect Unit
bindOverNode s f = bindNodeEvent s "overNode" f
...
...
src/Gargantext/Hooks/Sigmax/Types.purs
View file @
2fa0f2d8
...
...
@@ -40,6 +40,7 @@ type Node = (
, equilateral :: { numPoints :: Int }
, gargType :: GT.Mode
, hidden :: Boolean
, highlighted :: Boolean
, id :: NodeId
, label :: String
, size :: Number
...
...
src/Gargantext/Utils/Set.purs
0 → 100644
View file @
2fa0f2d8
module Gargantext.Utils.Set where
import Data.Ord (class Ord)
import Data.Set as Set
-- | If `a` is in Set, remove it, otherwise add it
toggle :: forall a. Ord a => Set.Set a -> a -> Set.Set a
toggle s x = if Set.member x s then Set.delete x s else Set.insert x s
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment