whispervis/page.go

149 lines
3.3 KiB
Go

package main
import (
"fmt"
"runtime"
"github.com/divan/graphx/graph"
"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
}
// 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
}
// 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.")),
elem.Div(
vecty.Markup(
vecty.MarkupIf(!p.loaded, vecty.Style("visibility", "hidden")),
),
p.forceEditor,
p.updateButton(),
),
),
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
}
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)
}