Commit 2812ea2d authored by Loïck Bonniot's avatar Loïck Bonniot
Browse files

[d] Add basic dynamic view of events

parent 00f0e26a
Pipeline #495 passed with stage
...@@ -86,5 +86,17 @@ func (w *Window) DrawArrow(xa, ya, xb, yb float64, rgb uint32) { ...@@ -86,5 +86,17 @@ func (w *Window) DrawArrow(xa, ya, xb, yb float64, rgb uint32) {
brush.SetColor(color) brush.SetColor(color)
brush.SetStyle(ui.Qt_SolidPattern) brush.SetStyle(ui.Qt_SolidPattern)
scene.AddPathWithPathPenBrush(path, pen, brush) arrow := scene.AddPathWithPathPenBrush(path, pen, brush)
w.currentArrows = append(w.currentArrows, arrow)
}
func (w *Window) RemoveArrows() {
scene := w.graphics.Scene()
for _, arrow := range w.currentArrows {
scene.RemoveItem(&arrow.QGraphicsItem)
defer arrow.Delete()
}
w.currentArrows = nil
} }
package gui
import (
"fmt"
"time"
"math"
)
// TEMPORARY
const quantum = 100 // discretization argument for events (ns)
const speed = 500 // duration of a quantum (ms)
func (w *Window) StartSimulation() {
w.ticker = time.NewTicker(speed * time.Millisecond)
go subroutine(w)
}
func (w *Window) DrawEvent(e *Event) {
xa, ya := w.GetClientPosition(e.Sender)
xb, yb := w.GetClientPosition(e.Receiver)
w.DrawArrow(xa, ya, xb, yb, colors["red"])
}
func (w *Window) PrintQuantumInformation() {
beginning := w.scene.Events[0].Date.UnixNano()
totalDuration := w.scene.Events[len(w.scene.Events) - 1].Date.UnixNano() - beginning
nbQuantum := math.Ceil(float64(totalDuration) / quantum)
durationFromBeginning := w.scene.currentTime.UnixNano() - beginning
currentQuantum := math.Ceil(float64(durationFromBeginning) / quantum)+1
w.progress.SetText(fmt.Sprint(currentQuantum, " / ", nbQuantum))
}
func subroutine(w *Window) {
for _ = range w.ticker.C {
nbEvents := len(w.scene.Events)
if w.scene.currentEvent >= nbEvents {
// TODO disable looping if needed
w.RemoveArrows()
w.scene.currentEvent = 0 // loop
w.Log("Restarting simulation...")
continue
}
// Remove arrows from last tick
w.RemoveArrows()
// Check that we have a least one event to read
if nbEvents == 0 {
continue
}
// Init first time
if w.scene.currentEvent == 0 {
w.scene.currentTime = w.scene.Events[0].Date
}
endOfQuantum := w.scene.currentTime.Add(quantum * time.Nanosecond)
for i := w.scene.currentEvent; i < nbEvents; i++ {
e := w.scene.Events[i]
if e.Date.After(endOfQuantum) || e.Date.Equal(endOfQuantum) {
break
}
w.DrawEvent(&e)
w.scene.currentEvent++
}
w.PrintQuantumInformation()
w.scene.currentTime = endOfQuantum
}
}
...@@ -2,8 +2,27 @@ package gui ...@@ -2,8 +2,27 @@ package gui
import ( import (
"time" "time"
"github.com/visualfc/goqt/ui"
) )
// Window contains all information used to make the demonstrator works.
// It extends QMainWindow and cache several graphic informations.
// Do not attempt to instantiante it directly, use `NewWindow` function instead.
type Window struct {
*ui.QMainWindow
logField *ui.QTextEdit
graphics *ui.QGraphicsView
progress *ui.QLabel
scene *Scene
circleSize float64
pixmaps map[string]*ui.QPixmap
currentArrows []*ui.QGraphicsPathItem
ticker *time.Ticker
}
// Client represents a DFSSC instance // Client represents a DFSSC instance
type Client struct { type Client struct {
Name string Name string
...@@ -23,8 +42,7 @@ type Event struct { ...@@ -23,8 +42,7 @@ type Event struct {
Type EventType Type EventType
Sender int Sender int
Receiver int Receiver int
Date *time.Time Date time.Time
Duration *time.Duration
} }
// Scene holds the global scene for registered clients and signature events // Scene holds the global scene for registered clients and signature events
...@@ -32,5 +50,6 @@ type Scene struct { ...@@ -32,5 +50,6 @@ type Scene struct {
Clients []Client Clients []Client
Events []Event Events []Event
currentEvent int currentTime time.Time
currentEvent int
} }
...@@ -141,7 +141,7 @@ ...@@ -141,7 +141,7 @@
<item> <item>
<widget class="QSlider" name="speedSlider"> <widget class="QSlider" name="speedSlider">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
...@@ -157,6 +157,22 @@ ...@@ -157,6 +157,22 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="progressLabel">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
......
...@@ -2,21 +2,12 @@ package gui ...@@ -2,21 +2,12 @@ package gui
import ( import (
"math" "math"
"time"
"dfss" "dfss"
"github.com/visualfc/goqt/ui" "github.com/visualfc/goqt/ui"
) )
type Window struct {
*ui.QMainWindow
logField *ui.QTextEdit
graphics *ui.QGraphicsView
scene *Scene
circleSize float64
pixmaps map[string]*ui.QPixmap
}
func NewWindow() *Window { func NewWindow() *Window {
file := ui.NewFileWithName(":/widget.ui") file := ui.NewFileWithName(":/widget.ui")
loader := ui.NewUiLoader() loader := ui.NewUiLoader()
...@@ -36,6 +27,7 @@ func NewWindow() *Window { ...@@ -36,6 +27,7 @@ func NewWindow() *Window {
// Load dynamic elements from driver // Load dynamic elements from driver
w.logField = ui.NewTextEditFromDriver(widget.FindChild("logField")) w.logField = ui.NewTextEditFromDriver(widget.FindChild("logField"))
w.graphics = ui.NewGraphicsViewFromDriver(widget.FindChild("graphicsView")) w.graphics = ui.NewGraphicsViewFromDriver(widget.FindChild("graphicsView"))
w.progress = ui.NewLabelFromDriver(widget.FindChild("progressLabel"))
// Load pixmaps // Load pixmaps
w.pixmaps = map[string]*ui.QPixmap{ w.pixmaps = map[string]*ui.QPixmap{
...@@ -56,8 +48,15 @@ func NewWindow() *Window { ...@@ -56,8 +48,15 @@ func NewWindow() *Window {
Client{"signer2@insa-rennes.fr"}, Client{"signer2@insa-rennes.fr"},
Client{"signer3@dfss.com"}, Client{"signer3@dfss.com"},
} }
w.scene.Events = []Event{
Event{PROMISE, 0, 1, time.Unix(0, 5)},
Event{SIGNATURE, 1, 2, time.Unix(0, 15)},
Event{PROMISE, 1, 0, time.Unix(0, 134)},
Event{OTHER, 0, 1, time.Unix(0, 402)},
}
w.StatusBar().ShowMessage("Ready") w.StatusBar().ShowMessage("Ready")
w.StartSimulation()
return w return w
} }
...@@ -97,7 +96,6 @@ func (w *Window) OnResizeEvent(ev *ui.QResizeEvent) bool { ...@@ -97,7 +96,6 @@ func (w *Window) OnResizeEvent(ev *ui.QResizeEvent) bool {
} }
func (w *Window) initScene() { func (w *Window) initScene() {
// Save old scene // Save old scene
oldScene := w.graphics.Scene() oldScene := w.graphics.Scene()
...@@ -113,14 +111,9 @@ func (w *Window) initScene() { ...@@ -113,14 +111,9 @@ func (w *Window) initScene() {
w.DrawClients() w.DrawClients()
w.DrawServers() w.DrawServers()
// TEST
xa, ya := w.GetClientPosition(0)
xb, yb := w.GetClientPosition(1)
w.DrawArrow(xa, ya, xb, yb, colors["red"])
w.DrawArrow(xb, yb, xa, ya, colors["red"])
// Purge // Purge
if oldScene != nil { if oldScene != nil {
oldScene.Delete() w.RemoveArrows()
defer oldScene.Delete()
} }
} }
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