First protocol editor interface prototype working

This commit is contained in:
Marcel M. Otte 2023-01-04 13:38:16 +01:00
parent 6b310e4b89
commit b8c3d7f856
8 changed files with 148 additions and 30 deletions

View File

@ -9,6 +9,7 @@ import (
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
"gitea.mmo.to/ProtocolPacketForger/ppf/internal/ui" "gitea.mmo.to/ProtocolPacketForger/ppf/internal/ui"
"gitea.mmo.to/ProtocolPacketForger/ppf/protocol"
) )
var fyneApp fyne.App var fyneApp fyne.App
@ -17,7 +18,7 @@ var w fyne.Window
func Appmain() { func Appmain() {
fyneApp = app.New() fyneApp = app.New()
w = fyneApp.NewWindow("ProtocolPacketForger") w = fyneApp.NewWindow("ProtocolPacketForger")
w.Resize(fyne.NewSize(800, 600)) w.Resize(fyne.NewSize(1024, 768))
w.SetContent(CreateApp()) w.SetContent(CreateApp())
@ -27,14 +28,14 @@ func Appmain() {
type ppfApp struct { type ppfApp struct {
// Container for the borderlayout // Container for the borderlayout
Toolbar fyne.CanvasObject Toolbar fyne.CanvasObject
Metadata *fyne.Container Metadata *Metadata
Extensions *fyne.Container Extensions *fyne.Container
ContextBar *fyne.Container ContextBar *fyne.Container
ContentTabs *fyne.Container ContentTabs *fyne.Container
Workarea *fyne.Container Workarea *fyne.Container
// Once initialized metadata containers for swapping // Once initialized metadata containers for swapping
ProtocolMeta *fyne.Container ProtocolMeta *ProtocolMetadata
PacketMeta *fyne.Container PacketMeta *PacketMetadata
// Global important stuff // Global important stuff
Settings map[string]string Settings map[string]string
ProtocolForging bool ProtocolForging bool
@ -45,17 +46,32 @@ type ppfApp struct {
var ppf ppfApp var ppf ppfApp
type Metadata struct {
Representation *fyne.Container
}
type PacketMetadata struct {
Metadata
}
type ProtocolMetadata struct {
Metadata
NameValue *widget.Entry
VersionValue *widget.Entry
ExtendsValue *widget.Entry
DescValue *widget.Entry
}
func CreateApp() *fyne.Container { func CreateApp() *fyne.Container {
ppf.Toolbar = CreateToolbar() ppf.Toolbar = CreateToolbar()
ppf.Workarea = CreateWorkarea() ppf.Workarea = CreateWorkarea()
ppf.Extensions = container.NewCenter() ppf.Extensions = container.NewCenter()
ppf.Metadata = container.NewCenter() ppf.ProtocolMeta = CreateMetadataProtocol()
ppf.ContextBar = container.NewCenter() ppf.ContextBar = container.NewCenter()
return container.NewBorder( return container.NewBorder(
ppf.Toolbar, ppf.Toolbar,
ppf.Metadata,
ppf.ContextBar, ppf.ContextBar,
ppf.Metadata.Representation,
ppf.Extensions, ppf.Extensions,
container.NewVScroll(ppf.Workarea), container.NewVScroll(ppf.Workarea),
) )
@ -92,7 +108,8 @@ func CreateWorkarea() *fyne.Container {
return ui.GetProtocolEditor().Representation return ui.GetProtocolEditor().Representation
} }
func CreateMetadataProtocol() *fyne.Container { func CreateMetadataProtocol() *ProtocolMetadata {
md := ProtocolMetadata{}
vbox := container.NewVBox() vbox := container.NewVBox()
vbox.Add(widget.NewLabel("Protocol Metadata")) vbox.Add(widget.NewLabel("Protocol Metadata"))
form := container.New(layout.NewFormLayout()) form := container.New(layout.NewFormLayout())
@ -107,11 +124,12 @@ func CreateMetadataProtocol() *fyne.Container {
multiline := widget.NewMultiLineEntry() multiline := widget.NewMultiLineEntry()
multiline.SetMinRowsVisible(3) multiline.SetMinRowsVisible(3)
vbox.Add(multiline) vbox.Add(multiline)
md.Representation = vbox
return vbox return &md
} }
func CreateMetadataPacket() *fyne.Container { func CreateMetadataPacket() *PacketMetadata {
md := PacketMetadata{}
vbox := container.NewVBox() vbox := container.NewVBox()
vbox.Add(widget.NewLabel("Packet Metadata")) vbox.Add(widget.NewLabel("Packet Metadata"))
form := container.New(layout.NewFormLayout()) form := container.New(layout.NewFormLayout())
@ -122,5 +140,9 @@ func CreateMetadataPacket() *fyne.Container {
multiline := widget.NewMultiLineEntry() multiline := widget.NewMultiLineEntry()
multiline.SetMinRowsVisible(3) multiline.SetMinRowsVisible(3)
vbox.Add(multiline) vbox.Add(multiline)
return vbox return &md
}
func UpdateProtocolMetadata(prot *protocol.ProtocolStructure) {
// md := ppfApp.ProtocolMeta
} }

View File

@ -2,11 +2,14 @@ package ui
import ( import (
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
"gitea.mmo.to/ProtocolPacketForger/ppf/protocolctl"
) )
func GetAdder(pEd *ProtocolEditor) *widget.Button { func GetAdder(pEd *ProtocolEditor) *widget.Button {
fieldAdder := widget.NewButton("Add Field", func() { fieldAdder := widget.NewButton("Add Field", func() {
pEd.AddFieldCreator(CreateFieldEditor()) f := protocolctl.NewEmptyField()
index := protocolctl.AppendField(pEd.Reference, f)
pEd.AddFieldCreator(CreateFieldEditor(pEd, index, f))
}) })
return fieldAdder return fieldAdder
} }

View File

@ -1,11 +1,16 @@
package ui package ui
import ( import (
"fmt"
"strconv"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
"gitea.mmo.to/ProtocolPacketForger/ppf/protocol" "gitea.mmo.to/ProtocolPacketForger/ppf/protocol"
"gitea.mmo.to/ProtocolPacketForger/ppf/protocolctl"
) )
type FieldEditor struct { type FieldEditor struct {
@ -16,30 +21,72 @@ type FieldEditor struct {
SizeLabel *widget.Label SizeLabel *widget.Label
SizeValue *widget.Entry SizeValue *widget.Entry
SizeInBits bool SizeInBits bool
OptionalCheck *widget.Check
PayloadCheck *widget.Check
// to be filled with needed things // to be filled with needed things
Reference *protocol.Field Reference *protocol.Field
Index int
} }
func CreateFieldEditor() *FieldEditor { func CreateFieldEditor(ed *ProtocolEditor, index int, ref *protocol.Field) *FieldEditor {
fc := &FieldEditor{} fc := &FieldEditor{}
fc.Reference = ref
fc.Index = index
setfunc := func(s string) {
bits := 0
if !fc.SizeInBits {
bits, _ = strconv.Atoi(fc.SizeValue.Text)
bits *= 8
} else {
bits, _ = strconv.Atoi(fc.SizeValue.Text)
}
protocolctl.UpdateFieldByElement(
ed.Reference,
fc.Index,
protocolctl.NewField(
fc.NameValue.Text,
fc.DescValue.Text,
fc.RegExValue.Text,
bits,
nil, //TODO: implement subfields
fc.OptionalCheck.Checked,
fc.PayloadCheck.Checked,
),
)
fmt.Printf("%s", protocolctl.ToJson(ed.Reference))
}
fc.Representation = container.New(layout.NewFormLayout()) fc.Representation = container.New(layout.NewFormLayout())
fc.Representation.Add(widget.NewLabel("")) toolbar := widget.NewToolbar()
fc.Representation.Add(widget.NewLabel("Field Values")) toolbar.Append(widget.NewToolbarAction(theme.DeleteIcon(), func() {
protocolctl.RemoveFieldByElement(ed.Reference, fc.Index)
ed.Redraw()
}))
fc.Representation.Add(toolbar)
addtool := widget.NewToolbar()
addtool.Append(widget.NewToolbarSpacer())
addtool.Append(widget.NewToolbarAction(theme.ContentAddIcon(), func() {
protocolctl.AddField(ed.Reference, fc.Index+1, protocolctl.NewEmptyField())
ed.Redraw()
}))
fc.Representation.Add(container.NewBorder(nil, nil, nil, addtool, widget.NewLabel("Field Values")))
fc.Representation.Add(widget.NewLabel("Name")) fc.Representation.Add(widget.NewLabel("Name"))
fc.NameValue = widget.NewEntry() fc.NameValue = widget.NewEntry()
fc.NameValue.OnChanged = setfunc
fc.Representation.Add(fc.NameValue) fc.Representation.Add(fc.NameValue)
fc.Representation.Add(widget.NewLabel("Description")) fc.Representation.Add(widget.NewLabel("Description"))
fc.DescValue = widget.NewEntry() fc.DescValue = widget.NewEntry()
fc.DescValue.MultiLine = true fc.DescValue.MultiLine = true
fc.DescValue.OnChanged = setfunc
fc.DescValue.SetMinRowsVisible(3) fc.DescValue.SetMinRowsVisible(3)
fc.Representation.Add(fc.DescValue) fc.Representation.Add(fc.DescValue)
fc.Representation.Add(widget.NewLabel("RegEx")) fc.Representation.Add(widget.NewLabel("RegEx"))
fc.RegExValue = widget.NewEntry() fc.RegExValue = widget.NewEntry()
fc.RegExValue.OnChanged = setfunc
fc.Representation.Add(fc.RegExValue) fc.Representation.Add(fc.RegExValue)
fc.SizeLabel = widget.NewLabel("Bytes") fc.SizeLabel = widget.NewLabel("Bytes")
@ -51,9 +98,31 @@ func CreateFieldEditor() *FieldEditor {
fc.SizeLabel.SetText("Bits") fc.SizeLabel.SetText("Bits")
} }
fc.SizeInBits = !fc.SizeInBits fc.SizeInBits = !fc.SizeInBits
setfunc("") // bogus call to reflect the change
}) })
fc.Representation.Add(container.NewHBox(toggleBtn, fc.SizeLabel)) fc.Representation.Add(container.NewHBox(toggleBtn, fc.SizeLabel))
fc.SizeValue = widget.NewEntry() fc.SizeValue = widget.NewEntry()
fc.SizeValue.OnChanged = setfunc
fc.Representation.Add(fc.SizeValue) fc.Representation.Add(fc.SizeValue)
fc.Representation.Add(widget.NewLabel("Settings"))
fc.OptionalCheck = widget.NewCheck("Optional", func(b bool) {
fc.Reference.Optional = b
setfunc("")
})
fc.PayloadCheck = widget.NewCheck("Payload", func(b bool) {
fc.Reference.Payload = b
setfunc("")
})
fc.Representation.Add(container.NewHBox(fc.OptionalCheck, fc.PayloadCheck))
fc.NameValue.Text = fc.Reference.Name
fc.DescValue.Text = fc.Reference.Desc
fc.RegExValue.Text = fc.Reference.Regex
fc.SizeValue.Text = strconv.Itoa(fc.Reference.Size)
fc.SizeInBits = true
fc.SizeLabel.SetText("Bits")
fc.OptionalCheck.Checked = fc.Reference.Optional
fc.PayloadCheck.Checked = fc.Reference.Payload
fc.Representation.Refresh()
return fc return fc
} }

View File

@ -1,6 +1,8 @@
package ui package ui
import ( import (
"fmt"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"gitea.mmo.to/ProtocolPacketForger/ppf/protocol" "gitea.mmo.to/ProtocolPacketForger/ppf/protocol"
@ -15,7 +17,7 @@ type ProtocolEditor struct {
} }
func GetProtocolEditor() *ProtocolEditor { func GetProtocolEditor() *ProtocolEditor {
container := container.NewGridWrap(fyne.NewSize(300, 300)) container := container.NewGridWrap(fyne.NewSize(300, 400))
protocolEditor := &ProtocolEditor{container, []*FieldEditor{}, protocolctl.NewProtocolStructure()} protocolEditor := &ProtocolEditor{container, []*FieldEditor{}, protocolctl.NewProtocolStructure()}
container.Add(GetAdder(protocolEditor)) container.Add(GetAdder(protocolEditor))
return protocolEditor return protocolEditor
@ -27,9 +29,13 @@ func (ed *ProtocolEditor) AddFieldCreator(fieldCreator *FieldEditor) {
} }
func (ed *ProtocolEditor) Redraw() { func (ed *ProtocolEditor) Redraw() {
json := protocolctl.ToJson(ed.Reference)
fmt.Printf("%s", json)
ed.Representation.RemoveAll() ed.Representation.RemoveAll()
for _, v := range ed.Fields { for i, v := range ed.Reference.Structure {
ed.Representation.Add(v.Representation) ed.Representation.Add(CreateFieldEditor(ed, i, v).Representation)
}
if len(ed.Reference.Structure) == 0 {
ed.Representation.Add(GetAdder(ed))
} }
ed.Representation.Add(GetAdder(ed))
} }

View File

@ -6,7 +6,7 @@ type Field struct {
Name string // Name of the Field Name string // Name of the Field
Desc string // Lengthy description Desc string // Lengthy description
Regex string // Regex to recognize values Regex string // Regex to recognize values
Size uint // Size in bits! Size int // Size in bits!
SubFields []Field // Possible sub-fields SubFields []Field // Possible sub-fields
Optional bool // Is this field required? Optional bool // Is this field required?
Payload bool // Is this field the payload or next protocol level? Payload bool // Is this field the payload or next protocol level?

View File

@ -2,7 +2,7 @@ package protocol
type ProtocolStructure struct { type ProtocolStructure struct {
Metadata DOPMeta Metadata DOPMeta
Structure []Field Structure []*Field
DefaultValues []DefaultValue DefaultValues []DefaultValue
JavaScript string JavaScript string
} }

View File

@ -34,11 +34,16 @@ func UpdateMetaData(
prot.Metadata.LowerLayerIdentification = lowerLayerIdent prot.Metadata.LowerLayerIdentification = lowerLayerIdent
} }
func NewEmptyField() *protocol.Field {
f := protocol.Field{}
return &f
}
func NewField( func NewField(
name string, name string,
desc string, desc string,
regex string, regex string,
size uint, size int,
subfields []protocol.Field, subfields []protocol.Field,
optional bool, optional bool,
payload bool, payload bool,
@ -55,8 +60,21 @@ func NewField(
return &f return &f
} }
func AppendField(prot *protocol.ProtocolStructure, field *protocol.Field) { func AppendField(prot *protocol.ProtocolStructure, field *protocol.Field) int {
prot.Structure = append(prot.Structure, *field) i := len(prot.Structure)
prot.Structure = append(prot.Structure, field)
return i
}
func AddField(prot *protocol.ProtocolStructure, index int, field *protocol.Field) {
if len(prot.Structure) == index {
AppendField(prot, field)
return
}
ret := make([]*protocol.Field, 0)
ret = append(ret, prot.Structure[:index]...)
ret = append(ret, field)
ret = append(ret, prot.Structure[index:]...)
prot.Structure = ret
} }
func UpdateFieldByName(prot *protocol.ProtocolStructure, name string, field *protocol.Field) { func UpdateFieldByName(prot *protocol.ProtocolStructure, name string, field *protocol.Field) {
@ -67,12 +85,12 @@ func UpdateFieldByName(prot *protocol.ProtocolStructure, name string, field *pro
} }
} }
if fnd != -1 { if fnd != -1 {
prot.Structure[fnd] = *field prot.Structure[fnd] = field
} }
} }
func UpdateFieldByElement(prot *protocol.ProtocolStructure, element int, field *protocol.Field) { func UpdateFieldByElement(prot *protocol.ProtocolStructure, element int, field *protocol.Field) {
prot.Structure[element] = *field prot.Structure[element] = field
} }
func RemoveFieldByName(prot *protocol.ProtocolStructure, name string) { func RemoveFieldByName(prot *protocol.ProtocolStructure, name string) {
@ -89,7 +107,7 @@ func RemoveFieldByName(prot *protocol.ProtocolStructure, name string) {
} }
func RemoveFieldByElement(prot *protocol.ProtocolStructure, field int) { func RemoveFieldByElement(prot *protocol.ProtocolStructure, field int) {
ret := make([]protocol.Field, 0) ret := make([]*protocol.Field, 0)
ret = append(ret, prot.Structure[:field]...) ret = append(ret, prot.Structure[:field]...)
ret = append(ret, prot.Structure[field+1:]...) ret = append(ret, prot.Structure[field+1:]...)
prot.Structure = ret prot.Structure = ret
@ -111,7 +129,7 @@ func LoadNew(path string) (*protocol.ProtocolStructure, error) {
} }
func ToJson(prot *protocol.ProtocolStructure) string { func ToJson(prot *protocol.ProtocolStructure) string {
data, err := json.Marshal(*prot) data, err := json.MarshalIndent(*prot, "", " ")
if err != nil { if err != nil {
return "" return ""
} }
@ -119,7 +137,7 @@ func ToJson(prot *protocol.ProtocolStructure) string {
} }
func Save(prot *protocol.ProtocolStructure, path string) error { func Save(prot *protocol.ProtocolStructure, path string) error {
data, err := json.Marshal(*prot) data, err := json.MarshalIndent(*prot, "", " ")
if err != nil { if err != nil {
return err return err
} }

View File

@ -49,7 +49,7 @@ func GenerateFields() []protocol.Field {
fmt.Sprintf("testfield%d", i), fmt.Sprintf("testfield%d", i),
fmt.Sprintf("Description %d", i), fmt.Sprintf("Description %d", i),
"", "",
uint(i*8), int(i*8),
nil, nil,
false, false,
false, false,