2018-09-06 12:15:55 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2018-09-06 15:37:46 +00:00
|
|
|
"fmt"
|
|
|
|
"runtime"
|
|
|
|
|
|
|
|
"github.com/divan/graphx/graph"
|
2018-09-06 12:15:55 +00:00
|
|
|
"github.com/divan/graphx/layout"
|
|
|
|
"github.com/gopherjs/gopherjs/js"
|
|
|
|
"github.com/gopherjs/vecty"
|
|
|
|
"github.com/gopherjs/vecty/elem"
|
|
|
|
"github.com/gopherjs/vecty/event"
|
|
|
|
"github.com/lngramos/three"
|
|
|
|
"github.com/status-im/whispervis/widgets"
|
|
|
|
"github.com/vecty/vthree"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Page is our main page component.
|
|
|
|
type Page struct {
|
|
|
|
vecty.Core
|
|
|
|
|
|
|
|
layout *layout.Layout
|
|
|
|
|
|
|
|
scene *three.Scene
|
|
|
|
camera three.PerspectiveCamera
|
|
|
|
renderer *three.WebGLRenderer
|
|
|
|
graph *three.Group
|
|
|
|
nodes *three.Group
|
|
|
|
edges *three.Group
|
|
|
|
controls TrackBallControl
|
|
|
|
|
|
|
|
autoRotate bool
|
|
|
|
|
|
|
|
loaded bool
|
|
|
|
loader *widgets.Loader
|
|
|
|
forceEditor *widgets.ForceEditor
|
|
|
|
}
|
|
|
|
|
2018-09-06 15:37:46 +00:00
|
|
|
// Page creates and inits new app page.
|
|
|
|
func NewPage(g *graph.Graph, steps int) *Page {
|
|
|
|
forceEditor := widgets.NewForceEditor()
|
|
|
|
config := forceEditor.Config()
|
|
|
|
l := layout.NewFromConfig(g, config)
|
|
|
|
page := &Page{
|
|
|
|
layout: l,
|
|
|
|
loader: widgets.NewLoader(steps),
|
|
|
|
forceEditor: forceEditor,
|
|
|
|
}
|
|
|
|
return page
|
|
|
|
}
|
|
|
|
|
2018-09-06 12:15:55 +00:00
|
|
|
// Render implements the vecty.Component interface.
|
|
|
|
func (p *Page) Render() vecty.ComponentOrHTML {
|
|
|
|
return elem.Body(
|
|
|
|
elem.Div(
|
|
|
|
vecty.Markup(
|
|
|
|
vecty.Class("pure-g"),
|
|
|
|
vecty.Style("height", "100%"),
|
|
|
|
),
|
|
|
|
elem.Div(
|
|
|
|
vecty.Markup(vecty.Class("pure-u-1-5")),
|
|
|
|
elem.Heading1(vecty.Text("Whisper Message Propagation")),
|
|
|
|
elem.Paragraph(vecty.Text("This visualization represents message propagation in the p2p network.")),
|
2018-09-06 14:43:42 +00:00
|
|
|
elem.Div(
|
|
|
|
vecty.Markup(
|
|
|
|
vecty.MarkupIf(!p.loaded, vecty.Style("visibility", "hidden")),
|
|
|
|
),
|
|
|
|
p.forceEditor,
|
2018-09-06 15:37:46 +00:00
|
|
|
p.updateButton(),
|
2018-09-06 14:43:42 +00:00
|
|
|
),
|
2018-09-06 12:15:55 +00:00
|
|
|
),
|
|
|
|
elem.Div(
|
|
|
|
vecty.Markup(vecty.Class("pure-u-4-5")),
|
|
|
|
vecty.If(p.loaded,
|
|
|
|
vthree.WebGLRenderer(vthree.WebGLOptions{
|
|
|
|
Init: p.init,
|
|
|
|
Shutdown: p.shutdown,
|
|
|
|
}),
|
|
|
|
),
|
|
|
|
vecty.If(!p.loaded, p.loader),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
vecty.Markup(
|
|
|
|
event.KeyDown(p.KeyListener),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Page) renderWebGLCanvas() vecty.Component {
|
|
|
|
return vthree.WebGLRenderer(vthree.WebGLOptions{
|
|
|
|
Init: p.init,
|
|
|
|
Shutdown: p.shutdown,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Page) init(renderer *three.WebGLRenderer) {
|
|
|
|
windowWidth := js.Global.Get("innerWidth").Float()*80/100 - 20
|
|
|
|
windowHeight := js.Global.Get("innerHeight").Float() - 20
|
|
|
|
|
|
|
|
p.renderer = renderer
|
|
|
|
p.renderer.SetSize(windowWidth, windowHeight, true)
|
|
|
|
|
|
|
|
devicePixelRatio := js.Global.Get("devicePixelRatio").Float()
|
|
|
|
p.renderer.SetPixelRatio(devicePixelRatio)
|
|
|
|
|
|
|
|
p.InitScene(windowWidth, windowHeight)
|
|
|
|
|
|
|
|
p.CreateObjects()
|
|
|
|
|
|
|
|
p.animate()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Page) shutdown(renderer *three.WebGLRenderer) {
|
|
|
|
p.scene = nil
|
|
|
|
p.camera = three.PerspectiveCamera{}
|
|
|
|
p.renderer = nil
|
|
|
|
p.graph, p.nodes, p.edges = nil, nil, nil
|
|
|
|
}
|
2018-09-06 15:37:46 +00:00
|
|
|
|
|
|
|
func (p *Page) updateButton() *vecty.HTML {
|
|
|
|
return elem.Div(
|
|
|
|
elem.Button(
|
|
|
|
vecty.Markup(
|
|
|
|
vecty.Class("pure-button"),
|
|
|
|
vecty.Style("background", "rgb(28, 184, 65)"),
|
|
|
|
vecty.Style("color", "white"),
|
|
|
|
vecty.Style("border-radius", "4px"),
|
|
|
|
event.Click(p.onUpdateClick),
|
|
|
|
),
|
|
|
|
vecty.Text("Update"),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Page) onUpdateClick(e *vecty.Event) {
|
|
|
|
fmt.Println("Clicked")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Page) StartSimulation() {
|
|
|
|
for i := 0; i < p.loader.Steps(); i++ {
|
|
|
|
p.layout.UpdatePositions()
|
|
|
|
p.loader.Inc()
|
|
|
|
vecty.Rerender(p.loader)
|
|
|
|
runtime.Gosched()
|
|
|
|
}
|
|
|
|
p.loaded = true
|
|
|
|
vecty.Rerender(p)
|
|
|
|
}
|