Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
gate
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
openmole
gate
Commits
8205d21e
Commit
8205d21e
authored
Sep 19, 2014
by
Mathieu leclaire
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Ugrade lib versions and add graph editor demonstrator
parent
e24c480e
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
406 additions
and
10 deletions
+406
-10
Client.scala
client/src/main/scala/fr/iscpif/client/Client.scala
+11
-1
FlowChart.scala
client/src/main/scala/fr/iscpif/client/FlowChart.scala
+285
-0
ScalaTraJSTagsWireRxBuild.scala
project/ScalaTraJSTagsWireRxBuild.scala
+6
-6
plugins.sbt
project/plugins.sbt
+1
-1
Server.scala
server/src/main/scala/fr/iscpif/app/Server.scala
+3
-2
d3.css
server/src/main/webapp/css/d3.css
+100
-0
No files found.
client/src/main/scala/fr/iscpif/client/Client.scala
View file @
8205d21e
...
...
@@ -26,7 +26,7 @@ object Client {
@JSExport
def
run
()
{
val
submitButton1
=
button
(
"Click me"
)(
/*
val submitButton1 = button("Click me")(
cursor := "pointer",
onclick := { () =>
Post[Api].hello(5).call().foreach { i =>
...
...
@@ -53,6 +53,16 @@ object Client {
dom.document.body.appendChild(h1(helloValue).render)
dom.document.body.appendChild(h1(caseClassValue).render)
}
}*/
val
nodes
=
scala
.
Array
(
new
Task
(
"1"
,
Var
(
"one"
),
Var
((
400
,
600
))),
new
Task
(
"2"
,
Var
(
"two"
),
Var
((
1000
,
600
))),
new
Task
(
"3"
,
Var
(
"three"
),
Var
((
400
,
100
))),
new
Task
(
"4"
,
Var
(
"four"
),
Var
((
1000
,
100
))),
new
Task
(
"5"
,
Var
(
"five"
),
Var
((
105
,
60
)))
)
val
edges
=
scala
.
Array
(
new
Edge
(
Var
(
nodes
(
0
)),
Var
(
nodes
(
1
))),
new
Edge
(
Var
(
nodes
(
0
)),
Var
(
nodes
(
2
))),
new
Edge
(
Var
(
nodes
(
3
)),
Var
(
nodes
(
1
))))
val
window
=
new
Window
(
nodes
,
edges
)
}
}
...
...
client/src/main/scala/fr/iscpif/client/FlowChart.scala
0 → 100644
View file @
8205d21e
package
client
/*
* Copyright (C) 21/08/14 // mathieu.leclaire@openmole.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import
fr.iscpif.scaladget.d3mapping._
import
org.scalajs.dom.
{
HTMLElement
,
Document
,
Element
}
import
org.scalajs.dom.SVGPoint
import
org.scalajs.dom
import
scalatags.JsDom.all._
import
scala.scalajs.js
//import scala.scalajs.js._
import
js.Dynamic.
{
literal
=>
lit
,
newInstance
=>
jsnew
}
import
rx._
import
fr.iscpif.scaladget.d3._
trait
GraphElement
<:
EventStates
{
def
literal
:
js.Dynamic
}
trait
EventStates
{
val
selected
:
Var
[
Boolean
]
=
Var
(
false
)
}
class
Task
(
val
id
:
String
,
val
title
:
Var
[
String
]
=
Var
(
""
),
val
location
:
Var
[(
Double
,
Double
)]
=
Var
((
0.0
,
0.0
)))
extends
GraphElement
{
def
literal
=
lit
(
"id"
->
id
,
"title"
->
title
(),
"x"
->
location
().
_1
,
"y"
->
location
().
_2
)
}
class
Edge
(
val
source
:
Var
[
Task
],
val
target
:
Var
[
Task
])
extends
GraphElement
{
def
literal
=
lit
(
"source"
->
source
().
literal
,
"target"
->
target
().
literal
)
}
class
Window
(
nodes
:
Array
[
Task
]
=
Array
(),
edges
:
Array
[
Edge
]
=
Array
())
{
val
svg
=
d3
.
select
(
"body"
)
.
append
(
"svg"
)
.
attr
(
"width"
,
"2500px"
)
.
attr
(
"height"
,
"2500px"
)
val
graph
=
new
GraphCreator
(
svg
,
nodes
,
edges
)
}
case
class
Consts
(
selectedClass
:
js.String
=
"selected"
,
circleGClass
:
String
=
"conceptG"
,
graphClass
:
js.String
=
"graph"
,
activeEditId
:
js.String
=
"active-editing"
,
DELETE_KEY
:
js.Number
=
46
,
nodeRadius
:
js.Number
=
50
)
class
GraphCreator
(
svgSelection
:
Selection
,
_tasks
:
Array
[
Task
],
_edges
:
Array
[
Edge
])
{
implicit
def
dynamicToString
(
d
:
js.Dynamic
)
:
String
=
d
.
asInstanceOf
[
js.String
]
implicit
def
dynamicToBoolean
(
d
:
js.Dynamic
)
:
Boolean
=
d
.
asInstanceOf
[
js.Boolean
]
// SVG DEFINITIONS //
val
consts
=
new
Consts
val
svgG
=
svgSelection
.
append
(
"g"
).
classed
(
consts
.
graphClass
,
true
)
val
dragLine
=
svgG
.
append
(
"svg:path"
)
.
attr
(
"class"
,
"link dragline hidden"
)
.
attr
(
"d"
,
"M0,0L0,0"
)
.
style
(
"marker-end"
,
"url(#mark-end-arrow)"
)
val
defs
=
svgSelection
.
append
(
"svg:defs"
)
val
pathRoot
=
svgG
.
append
(
"g"
)
val
circleRoot
=
svgG
.
append
(
"g"
)
val
mouseDownTask
:
Var
[
Option
[
Task
]]
=
Var
(
None
)
svgSelection
.
on
(
"mousemove"
,
(
_:
js.Any
,
_:
js.Number
)
=>
mousemove
)
.
on
(
"mouseup.scene"
,
(
_:
js.Any
,
_:
js.Number
)
=>
mouseup
)
// define arrow markers for graph links
defs
.
append
(
"svg:marker"
)
.
attr
(
"id"
,
"end-arrow"
)
.
attr
(
"viewBox"
,
"0 -5 10 10"
)
.
attr
(
"refX"
,
32
)
.
attr
(
"markerWidth"
,
3.5
)
.
attr
(
"markerHeight"
,
3.5
)
.
attr
(
"orient"
,
"auto"
)
.
append
(
"svg:path"
)
.
attr
(
"d"
,
"M0,-5L10,0L0,5"
)
// define arrow markers for leading arrow
defs
.
append
(
"svg:marker"
)
.
attr
(
"id"
,
"mark-end-arrow"
)
.
attr
(
"viewBox"
,
"0 -5 10 10"
)
.
attr
(
"refX"
,
7
)
.
attr
(
"markerWidth"
,
3.5
)
.
attr
(
"markerHeight"
,
3.5
)
.
attr
(
"orient"
,
"auto"
)
.
append
(
"svg:path"
)
.
attr
(
"d"
,
"M0,-5L10,0L0,5"
)
val
tasks
:
Var
[
Array
[
Var
[
Task
]]]
=
Var
(
Array
())
_tasks
.
map
{
addTask
}
val
edges
:
Var
[
Array
[
Var
[
Edge
]]]
=
Var
(
Array
())
_edges
.
map
{
addEdge
}
// GLOBAL EVENTS //
d3
.
select
(
dom
.
window
)
.
on
(
"keydown"
,
(
_:
js.Any
,
_:
js.Number
)
=>
{
d3
.
event
.
keyCode
match
{
case
consts
.
DELETE_KEY
=>
tasks
().
filter
(
t
=>
t
().
selected
()).
map
{
t
=>
removeTask
(
t
)
}
edges
().
filter
(
e
=>
e
().
selected
()).
map
{
e
=>
removeEdge
(
e
)
}
case
_
=>
}
})
def
mousemove
=
{
Seq
(
mouseDownTask
()).
flatten
.
map
{
t
=>
val
x
=
d3
.
event
.
clientX
val
y
=
d3
.
event
.
clientY
if
(
d3
.
event
.
shiftKey
)
{
dragLine
.
attr
(
"d"
,
"M"
+
t
.
location
().
_1
+
","
+
t
.
location
().
_2
+
"L"
+
x
+
","
+
y
)
}
else
{
t
.
location
()
=
(
x
,
y
)
}
}
}
def
mouseup
=
{
// Hide the drag line
mouseDownTask
()
=
None
dragLine
.
classed
(
"hidden"
,
true
)
.
style
(
"marker-end"
,
" "
)
}
// ADD, SELECT AND REMOVE ITEMS //
def
unselectTasks
=
tasks
().
foreach
{
t
=>
t
().
selected
()
=
false
}
def
unselectEdges
=
edges
().
foreach
{
e
=>
e
().
selected
()
=
false
}
def
removeTask
(
t
:
Var
[
Task
])
=
{
tasks
()
=
tasks
()
diff
Array
(
t
)
edges
()
=
edges
().
filterNot
(
e
=>
e
().
source
()
==
t
()
||
e
().
target
()
==
t
())
}
def
removeEdge
(
e
:
Var
[
Edge
])
=
{
edges
()
=
edges
()
diff
Array
(
e
)
}
def
addTask
(
id
:
String
,
title
:
String
,
x
:
Double
,
y
:
Double
)
:
Unit
=
addTask
(
new
Task
(
id
,
Var
(
title
),
Var
((
x
,
y
))))
def
addTask
(
task
:
Task
)
:
Unit
=
{
tasks
()
=
tasks
()
:+
Var
(
task
)
Obs
(
tasks
)
{
val
mysel
=
circleRoot
.
selectAll
(
"g"
).
data
(
tasks
(),
(
task
:
Var
[
Task
],
n
:
js.Number
)
=>
{
task
().
id
.
toString
})
val
newG
=
mysel
.
enter
().
append
(
"g"
)
newG
.
append
(
"circle"
).
attr
(
"r"
,
consts
.
nodeRadius
)
Rx
{
newG
.
classed
(
consts
.
circleGClass
,
true
)
.
attr
(
"transform"
,
(
task
:
Var
[
Task
])
=>
{
val
loc
=
task
().
location
()
"translate("
+
loc
.
_1
+
","
+
loc
.
_2
+
")"
})
newG
.
classed
(
consts
.
selectedClass
,
(
task
:
Var
[
Task
])
=>
{
task
().
selected
()
})
}
newG
.
on
(
"mousedown"
,
(
t
:
Var
[
Task
],
n
:
js.Number
)
=>
{
mouseDownTask
()
=
Some
(
t
())
d3
.
event
.
stopPropagation
unselectTasks
unselectEdges
t
().
selected
()
=
!
t
().
selected
()
if
(
d3
.
event
.
shiftKey
)
{
val
x
=
t
().
location
().
_1
val
y
=
t
().
location
().
_2
dragLine
.
style
(
"marker-end"
,
"url(#mark-end-arrow)"
)
.
classed
(
"hidden"
,
false
)
.
attr
(
"d"
,
"M"
+
x
+
","
+
y
+
"L"
+
x
+
","
+
y
)
}
})
.
on
(
"mouseup.task"
,
(
t
:
Var
[
Task
],
n
:
js.Number
)
=>
{
Seq
(
mouseDownTask
()).
flatten
.
map
{
mdt
=>
if
(
t
()
!=
mdt
)
{
addEdge
(
mdt
,
t
())
}
}
}
)
mysel
.
exit
().
remove
()
}
}
def
addEdge
(
source
:
Task
,
target
:
Task
)
:
Unit
=
addEdge
(
new
Edge
(
Var
(
source
),
Var
(
target
)))
def
addEdge
(
edge
:
Edge
)
:
Unit
=
{
edges
()
=
edges
()
:+
Var
(
edge
)
Obs
(
edges
)
{
val
mysel
=
pathRoot
.
selectAll
(
"path"
).
data
(
edges
(),
(
edge
:
Var
[
Edge
],
n
:
js.Number
)
=>
{
edge
().
source
().
id
+
"+"
+
edge
().
target
().
id
})
val
newPath
=
mysel
.
enter
().
append
(
"path"
)
Rx
{
newPath
.
style
(
"marker-end"
,
"url(#end-arrow)"
)
.
classed
(
"link"
,
true
)
.
attr
(
"d"
,
(
edge
:
Var
[
Edge
],
n
:
js.Number
)
=>
{
val
source
=
edge
().
source
().
location
()
val
target
=
edge
().
target
().
location
()
"M"
+
source
.
_1
+
","
+
source
.
_2
+
"L"
+
target
.
_1
+
","
+
target
.
_2
})
// update existing paths
newPath
.
style
(
"marker-end"
,
"url(#end-arrow)"
)
.
classed
(
consts
.
selectedClass
,
(
edge
:
Var
[
Edge
],
n
:
Number
)
=>
{
edge
().
selected
()
}
)
newPath
.
on
(
"mousedown"
,
(
edge
:
Var
[
Edge
],
n
:
js.Number
)
=>
{
unselectTasks
unselectEdges
edge
().
selected
()
=
!
edge
().
selected
()
})
}
mysel
.
exit
().
remove
()
}
}
}
\ No newline at end of file
project/ScalaTraJSTagsWireRxBuild.scala
View file @
8205d21e
...
...
@@ -29,12 +29,12 @@ object ScalaTraJSTagsWireRxBuild extends Build {
scalaVersion
:=
ScalaVersion
,
resolvers
++=
Resolvers
,
libraryDependencies
++=
Seq
(
"com.lihaoyi"
%%%
"autowire"
%
"0.2.
2
"
,
"com.lihaoyi"
%%%
"upickle"
%
"0.2.
2
"
,
"com.lihaoyi"
%%%
"autowire"
%
"0.2.
3
"
,
"com.lihaoyi"
%%%
"upickle"
%
"0.2.
4
"
,
"com.scalatags"
%%%
"scalatags"
%
"0.4.0"
,
"com.scalarx"
%%%
"scalarx"
%
"0.2.6"
,
"
org.scala-lang.modules.scalajs"
%%%
"scalajs-dom"
%
"0.6
"
,
"org.scala-lang.modules.scalajs"
%%%
"scalajs-
jquery
"
%
"0.6"
"
fr.iscpif"
%%%
"scaladget"
%
"0.1.0
"
,
"org.scala-lang.modules.scalajs"
%%%
"scalajs-
dom
"
%
"0.6"
),
//jsCall := "Client().run();",
outputPath
:=
"server/src/main/webapp/"
...
...
@@ -51,8 +51,8 @@ object ScalaTraJSTagsWireRxBuild extends Build {
scalaVersion
:=
ScalaVersion
,
resolvers
++=
Resolvers
,
libraryDependencies
++=
Seq
(
"com.lihaoyi"
%%
"autowire"
%
"0.2.
2
"
,
"com.lihaoyi"
%%
"upickle"
%
"0.2.
2
"
,
"com.lihaoyi"
%%
"autowire"
%
"0.2.
3
"
,
"com.lihaoyi"
%%
"upickle"
%
"0.2.
4
"
,
"com.scalatags"
%%
"scalatags"
%
"0.4.0"
,
"org.scalatra"
%%
"scalatra"
%
ScalatraVersion
,
"org.scalatra"
%%
"scalatra-specs2"
%
ScalatraVersion
%
"test"
,
...
...
project/plugins.sbt
View file @
8205d21e
...
...
@@ -5,6 +5,6 @@ resolvers ++= Seq(Resolver.url("scala-js-releases",
resolvers
+=
"Typesafe repository"
at
"http://repo.typesafe.com/typesafe/releases/"
addSbtPlugin
(
"fr.iscpif"
%%
"jsmanager"
%
"0.
2
.0"
)
addSbtPlugin
(
"fr.iscpif"
%%
"jsmanager"
%
"0.
4
.0"
)
addSbtPlugin
(
"org.scalatra.sbt"
%
"scalatra-sbt"
%
"0.3.5"
)
\ No newline at end of file
server/src/main/scala/fr/iscpif/app/Server.scala
View file @
8205d21e
...
...
@@ -33,8 +33,9 @@ class Server extends ScalatraServlet {
tags
.
html
(
tags
.
head
(
tags
.
meta
(
tags
.
httpEquiv
:=
"Content-Type"
,
tags
.
content
:=
"text/html; charset=UTF-8"
),
tags
.
script
(
tags
.
`type`
:=
"text/javascript"
,
tags
.
src
:=
"js/client-fastopt.js"
),
tags
.
script
(
tags
.
`type`
:=
"text/javascript"
,
tags
.
src
:=
"js/client-opt.js"
)
tags
.
link
(
tags
.
rel
:=
"stylesheet"
,
tags
.
`type`
:=
"text/css"
,
href
:=
"css/d3.css"
),
tags
.
script
(
tags
.
`type`
:=
"text/javascript"
,
tags
.
src
:=
"js/client-opt.js"
),
tags
.
script
(
tags
.
`type`
:=
"text/javascript"
,
tags
.
src
:=
"js/d3.v3.min.js"
)
),
tags
.
body
(
tags
.
onload
:=
"Client().run();"
)
)
...
...
server/src/main/webapp/css/d3.css
0 → 100644
View file @
8205d21e
body
{
margin
:
0
;
padding
:
0
;
overflow
:
hidden
;
}
p
{
text-align
:
center
;
overflow
:
overlay
;
position
:
relative
;
}
body
{
-webkit-touch-callout
:
none
;
-webkit-user-select
:
none
;
-khtml-user-select
:
none
;
-moz-user-select
:
none
;
-ms-user-select
:
none
;
user-select
:
none
;
background-color
:
rgb
(
248
,
248
,
248
)
}
#toolbox
{
position
:
absolute
;
bottom
:
0
;
left
:
0
;
margin-bottom
:
0.5em
;
margin-left
:
1em
;
border
:
2px
solid
#EEEEEE
;
border-radius
:
5px
;
padding
:
1em
;
z-index
:
5
;
}
#toolbox
input
{
width
:
30px
;
opacity
:
0.4
;
}
#toolbox
input
:hover
{
opacity
:
1
;
cursor
:
pointer
;
}
#hidden-file-upload
{
display
:
none
;
}
#download-input
{
margin
:
0
0.5em
;
}
.conceptG
text
{
pointer-events
:
none
;
}
marker
{
fill
:
#333
;
}
g
.conceptG
circle
{
fill
:
#F6FBFF
;
stroke
:
#333
;
stroke-width
:
2px
;
z-index
:
21
;
}
g
.conceptG
:hover
circle
{
fill
:
rgb
(
200
,
238
,
1
);
}
g
.selected
circle
{
fill
:
rgb
(
0
,
232
,
255
);
}
g
.selected
:hover
circle
{
fill
:
rgb
(
250
,
232
,
255
);
}
path
.link
{
fill
:
none
;
stroke
:
#333
;
stroke-width
:
6px
;
cursor
:
default
;
}
path
.link
:hover
{
stroke
:
rgb
(
94
,
196
,
204
);
}
g
.connect-node
circle
{
fill
:
#BEFFFF
;
}
path
.link.hidden
{
stroke-width
:
0
;
}
path
.link.selected
{
stroke
:
rgb
(
229
,
172
,
247
);
}
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