Editor is now fully in a DocTab

This commit is contained in:
Marcel M. Otte 2023-03-31 15:38:20 +02:00
parent b65c9c27f7
commit 52bff71153
4 changed files with 163 additions and 103 deletions

View File

@ -1,6 +1,7 @@
package ui package ui
import ( import (
"fmt"
"strings" "strings"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
@ -8,8 +9,6 @@ import (
"fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/theme" "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/protocolctl"
) )
type Representationer interface { type Representationer interface {
@ -24,8 +23,10 @@ type FileHandler interface {
SaveAs(path string) error SaveAs(path string) error
Close() error Close() error
Changed() SetChanged()
HasChanged() bool HasChanged() bool
GetReference() interface{}
} }
type ppfApp struct { type ppfApp struct {
@ -39,7 +40,7 @@ type ppfApp struct {
// tbd // tbd
// center opened objects // center opened objects
OpenTabs *container.DocTabs // DocTabs OpenTabs *container.DocTabs // DocTabs
OpenObjects []*FileHandler // actual files OpenObjects []FileHandler // actual files
// Global important stuff // Global important stuff
Settings map[string]interface{} Settings map[string]interface{}
@ -66,30 +67,20 @@ func NewPPF(fyneApp fyne.App, w fyne.Window) ppfApp {
PPF.App = fyneApp PPF.App = fyneApp
PPF.Window = w PPF.Window = w
PPF.Toolbar = CreateToolbar(fyneApp) PPF.Toolbar = CreateToolbar(fyneApp)
/*PPF.Workarea = CreateWorkarea() PPF.OpenTabs = CreateWorkarea()
PPF.Extensions = container.NewCenter()
PPF.ProtocolMeta = NewMetadataProtocol()
PPF.Metadata = &PPF.ProtocolMeta.Metadata
PPF.ContextBar = container.NewCenter() //*/
return PPF return PPF
} }
func (ppf *ppfApp) GetContainer() *fyne.Container { func (ppf *ppfApp) GetContainer() *fyne.Container {
return container.NewBorder( return container.NewBorder(
PPF.Toolbar, ppf.Toolbar, //top
nil, //PPF.ContextBar, nil, //bottom
nil, //PPF.Metadata.Representation, nil, //left // maybe Accordion with existing protocols, your protocols, your packets?
nil, //PPF.Extensions, nil, //right
PPF.OpenTabs, ppf.OpenTabs,
) )
} }
func (ppf *ppfApp) OpenFile(path string) {
pfh := LoadProtocolFileHandler(path)
ppf.OpenProtocolFiles = append(PPF.OpenProtocolFiles, pfh)
ppf.Workarea.Append(container.NewTabItem(pfh.Filename, pfh.GetWorkarea()))
}
func (ppf *ppfApp) NewProtocolFile() { func (ppf *ppfApp) NewProtocolFile() {
//TODO: show entry screen with choosable ways of: //TODO: show entry screen with choosable ways of:
// PROTOCOL editor // PROTOCOL editor
@ -99,32 +90,71 @@ func (ppf *ppfApp) NewProtocolFile() {
// create a binary packet // create a binary packet
// edit an existing binary packet // edit an existing binary packet
pfh := NewProtocolFileHandler() pfh := NewProtocolFileHandler()
PPF.OpenProtocolFiles = append(PPF.OpenProtocolFiles, pfh) ppf.OpenObjects = append(ppf.OpenObjects, pfh)
ppf.Workarea.Append(container.NewTabItem(pfh.Filename, pfh.GetWorkarea())) item := ppf.OpenTabs.Selected()
item.Text = pfh.Name()
item.Content = pfh.GetWorkarea()
} }
func (ppf *ppfApp) NewPacketFile() { func (ppf *ppfApp) NewPacketFile() {
} }
func (ppf *ppfApp) SaveFile(path string) { func (ppf *ppfApp) OpenProtocolFile(path string) {
item := ppf.Workarea.Selected() for _, v := range ppf.OpenTabs.Items {
for _, pfh := range ppf.OpenProtocolFiles { if v.Text == path {
if pfh.Filename == item.Text { // do not open a file twice!
protocolctl.Save(pfh.ProtocolEditor.Reference, path) ppf.OpenTabs.Select(v)
return
} }
} }
item.Text = path pfh := NewProtocolFileHandler()
ppf.Workarea.Refresh() pfh.Open(path)
ppf.OpenObjects = append(ppf.OpenObjects, pfh)
item := ppf.OpenTabs.Selected()
item.Text = pfh.Path()
item.Content = pfh.GetWorkarea()
} }
func (ppf *ppfApp) GetReferenceForFile(s string) *protocol.ProtocolStructure { func (ppf *ppfApp) OpenPacketFile(path string) {
for _, pfh := range ppf.OpenProtocolFiles {
if pfh.Filename == s { }
return pfh.ProtocolEditor.Reference
func (ppf *ppfApp) SaveFile(path string) {
item := ppf.OpenTabs.Selected()
for _, fh := range ppf.OpenObjects {
if fh.Path() == item.Text {
fh.SaveAs(path)
} }
} }
return nil // if there exists another one with the same path, (max one!!!)
existingTab := -1
for i, v := range ppf.OpenTabs.Items {
fmt.Printf("tab %d, path %s", i, v.Text)
if v.Text == path && i != ppf.OpenTabs.SelectedIndex() {
existingTab = i
}
}
if existingTab > 0 {
ppf.OpenTabs.Items = append(ppf.OpenTabs.Items[:existingTab], ppf.OpenTabs.Items[existingTab+1:]...)
fmt.Printf("removing %d", existingTab)
ppf.OpenTabs.Refresh()
}
item.Text = path
ppf.OpenTabs.Refresh()
}
func (ppf *ppfApp) NewFile() {
for _, v := range ppf.OpenTabs.Items {
if v.Text == "[new item dialog]" {
ppf.OpenTabs.Select(v)
return
}
}
item := container.NewTabItem("[new item dialog]", CreateNewObjectDialog().Representation())
ppf.OpenTabs.Append(item)
ppf.OpenTabs.Select(item)
} }
func CreateToolbar(fyneApp fyne.App) fyne.CanvasObject { func CreateToolbar(fyneApp fyne.App) fyne.CanvasObject {
@ -132,16 +162,8 @@ func CreateToolbar(fyneApp fyne.App) fyne.CanvasObject {
toolbar.Append(widget.NewToolbarAction(theme.ContentAddIcon(), func() { toolbar.Append(widget.NewToolbarAction(theme.ContentAddIcon(), func() {
PPF.NewFile() PPF.NewFile()
})) }))
toolbar.Append(widget.NewToolbarAction(theme.FolderOpenIcon(), func() {
dialog.NewFileOpen(func(uri fyne.URIReadCloser, err error) {
if uri == nil {
return
}
PPF.OpenFile(uri.URI().Path())
}, PPF.Window).Show()
}))
toolbar.Append(widget.NewToolbarAction(theme.DocumentSaveIcon(), func() { toolbar.Append(widget.NewToolbarAction(theme.DocumentSaveIcon(), func() {
if strings.HasPrefix(PPF.Workarea.Selected().Text, "*new") { if strings.HasPrefix(PPF.OpenTabs.Selected().Text, "*new") {
dialog.NewFileSave(func(uri fyne.URIWriteCloser, err error) { dialog.NewFileSave(func(uri fyne.URIWriteCloser, err error) {
if uri == nil { if uri == nil {
return return
@ -149,7 +171,7 @@ func CreateToolbar(fyneApp fyne.App) fyne.CanvasObject {
PPF.SaveFile(uri.URI().Path()) PPF.SaveFile(uri.URI().Path())
}, PPF.Window).Show() }, PPF.Window).Show()
} else { } else {
PPF.SaveFile(PPF.Workarea.Selected().Text) PPF.SaveFile(PPF.OpenTabs.Selected().Text)
} }
})) }))
toolbar.Append(widget.NewToolbarAction(theme.StorageIcon(), func() { toolbar.Append(widget.NewToolbarAction(theme.StorageIcon(), func() {
@ -175,15 +197,9 @@ func CreateToolbar(fyneApp fyne.App) fyne.CanvasObject {
func CreateWorkarea() *container.DocTabs { func CreateWorkarea() *container.DocTabs {
tabs := container.NewDocTabs() tabs := container.NewDocTabs()
tabs.OnClosed = func(ti *container.TabItem) { tabs.OnClosed = func(ti *container.TabItem) {
if len(tabs.Items) == 0 {
PPF.Metadata.Representation.Hide()
}
} }
tabs.OnSelected = func(ti *container.TabItem) { tabs.OnSelected = func(ti *container.TabItem) {
PPF.ProtocolMeta.SetProtocol(PPF.GetReferenceForFile(ti.Text))
PPF.Metadata = &PPF.ProtocolMeta.Metadata
PPF.Metadata.Representation.Refresh()
PPF.Metadata.Representation.Show()
} }
return tabs return tabs
} }

View File

@ -3,6 +3,8 @@ package ui
import ( import (
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
) )
@ -20,34 +22,49 @@ func CreateNewObjectDialog() *NewObjectDialog {
if pnod == nil { if pnod == nil {
pnod = &NewObjectDialog{} pnod = &NewObjectDialog{}
pnod.representation = container.NewMax(nil)
// representation // representation
// grid layout 100x100px elements in a center layout, 4 buttons, new Protocol, edit protocol, new Packet, edit Packet // grid layout 100x100px elements in a center layout, 4 buttons, new Protocol, edit protocol, new Packet, edit Packet
buttons := []widget.Button{} buttons := []*widget.Button{
buttons = append(buttons, *widget.NewButton("New protocol", func() { widget.NewButton("New protocol", func() {
PPF.NewProtocolFile() // two ways: either backreference to PPF, open new tab with file and close the NOD
})) // or replace the content of the tab of the NOD, with changing the title in OpenTabs backreference to PPF aswell
buttons = append(buttons, *widget.NewButton("Open/Edit protocol", func() { PPF.NewProtocolFile()
pnod.representation.RemoveAll() }),
pnod.representation.Add(pnod.protocolChooser) widget.NewButton("Open/Edit protocol", func() {
})) opendialog := dialog.NewFileOpen(func(uri fyne.URIReadCloser, err error) {
buttons = append(buttons, *widget.NewButton("New packet", func() { if uri == nil {
PPF.NewPacketFile() return
})) }
buttons = append(buttons, *widget.NewButton("Open/Edit packet", func() { PPF.OpenProtocolFile(uri.URI().Path())
pnod.representation.RemoveAll() }, PPF.Window)
pnod.representation.Add(pnod.packetChooser) opendialog.SetFilter(storage.NewExtensionFileFilter([]string{".protocoljson"}))
})) opendialog.Show()
selectgrid := container.NewGridWithColumns(2, nil) }),
widget.NewButton("New packet", func() {
PPF.NewPacketFile()
}),
widget.NewButton("Open/Edit packet", func() {
opendialog := dialog.NewFileOpen(func(uri fyne.URIReadCloser, err error) {
if uri == nil {
return
}
PPF.OpenPacketFile(uri.URI().Path())
}, PPF.Window)
opendialog.SetFilter(storage.NewExtensionFileFilter([]string{".packetjson"}))
opendialog.Show()
}),
}
selectgrid := container.NewGridWithColumns(2)
for _, v := range buttons { for _, v := range buttons {
selectgrid.Add(&v) selectgrid.Add(v)
} }
pnod.selection = container.NewMax(selectgrid) pnod.selection = container.NewMax(selectgrid)
pnod.representation = pnod.selection
pnod.representation.Add(pnod.selection) // add selection per default //pnod.representation.Add(pnod.selection) // add selection per default
// generate protocol chooser view // generate protocol chooser view
// App Tabs or vertical Accordion (doesnt exist yet) // App Tabs or vertical Accordion (doesnt exist yet)
pnod.protocolChooser = container.NewAppTabs(nil) //pnod.protocolChooser = container.NewAppTabs(nil)
// first tab -> official protocol repo, for viewing and editing/improvement // first tab -> official protocol repo, for viewing and editing/improvement
// file chooser embedded // file chooser embedded
// second tab -> own protocols, in a folder somewhere. // second tab -> own protocols, in a folder somewhere.

View File

@ -11,21 +11,18 @@ import (
type ProtocolEditor struct { type ProtocolEditor struct {
Representation *fyne.Container Representation *fyne.Container
FieldContainer *fyne.Container
Metadata *ProtocolMetadata
Fields []*FieldEditor Fields []*FieldEditor
Reference *protocol.ProtocolStructure Reference *protocol.ProtocolStructure
} }
func GetProtocolEditor() *ProtocolEditor {
container := container.NewGridWrap(fyne.NewSize(300, 400))
protocolEditor := &ProtocolEditor{container, []*FieldEditor{}, protocolctl.NewProtocolStructure()}
container.Add(GetAdder(protocolEditor))
return protocolEditor
}
func NewProtocolEditor(ref *protocol.ProtocolStructure) *ProtocolEditor { func NewProtocolEditor(ref *protocol.ProtocolStructure) *ProtocolEditor {
container := container.NewGridWrap(fyne.NewSize(300, 400)) metadata := NewMetadataProtocol()
protocolEditor := &ProtocolEditor{container, []*FieldEditor{}, ref} fields := container.NewGridWrap(fyne.NewSize(300, 400))
container := container.NewBorder(nil, nil, metadata.Representation, nil, container.NewVScroll(fields))
protocolEditor := &ProtocolEditor{container, fields, metadata, []*FieldEditor{}, ref}
protocolEditor.Redraw() protocolEditor.Redraw()
return protocolEditor return protocolEditor
} }
@ -38,11 +35,14 @@ func (ed *ProtocolEditor) AddFieldCreator(fieldCreator *FieldEditor) {
func (ed *ProtocolEditor) Redraw() { func (ed *ProtocolEditor) Redraw() {
json := protocolctl.ToJson(ed.Reference) json := protocolctl.ToJson(ed.Reference)
fmt.Printf("%s", json) fmt.Printf("%s", json)
ed.Representation.RemoveAll() ed.FieldContainer.RemoveAll()
// existing fields
for i, v := range ed.Reference.Structure { for i, v := range ed.Reference.Structure {
ed.Representation.Add(CreateFieldEditor(ed, i, v).Representation) ed.FieldContainer.Add(CreateFieldEditor(ed, i, v).Representation)
} }
if len(ed.Reference.Structure) == 0 { if len(ed.Reference.Structure) == 0 {
ed.Representation.Add(GetAdder(ed)) ed.FieldContainer.Add(GetAdder(ed))
} }
// Metadata
ed.Metadata.SetProtocol(ed.Reference)
} }

View File

@ -1,48 +1,75 @@
package ui package ui
import ( import (
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2"
"gitea.mmo.to/ProtocolPacketForger/ppf/protocol" "gitea.mmo.to/ProtocolPacketForger/ppf/protocol"
"gitea.mmo.to/ProtocolPacketForger/ppf/protocolctl" "gitea.mmo.to/ProtocolPacketForger/ppf/protocolctl"
) )
// implements FileHandler
type ProtocolFileHandler struct { type ProtocolFileHandler struct {
ProtocolEditor *ProtocolEditor ProtocolEditor *ProtocolEditor
Filename string name string
Changed bool path string
changed bool
Reference *protocol.ProtocolStructure Reference *protocol.ProtocolStructure
} }
func NewProtocolFileHandler() *ProtocolFileHandler { func NewProtocolFileHandler() *ProtocolFileHandler {
pfh := ProtocolFileHandler{} pfh := ProtocolFileHandler{}
pfh.Filename = "*new" pfh.name = "*new"
pfh.Changed = true pfh.changed = true
pfh.ProtocolEditor = GetProtocolEditor() pfh.ProtocolEditor = NewProtocolEditor(protocolctl.NewProtocolStructure())
return &pfh return &pfh
} }
func LoadProtocolFileHandler(path string) *ProtocolFileHandler { func (pfh *ProtocolFileHandler) Load() error {
pfh := ProtocolFileHandler{} prot, err := protocolctl.LoadNew(pfh.Path())
pfh.Filename = path
pfh.Load()
return &pfh
}
func (pfh *ProtocolFileHandler) Load() {
prot, err := protocolctl.LoadNew(pfh.Filename)
if err != nil { if err != nil {
// process error // process error
err = nil err = nil
} }
pfh.ProtocolEditor = NewProtocolEditor(prot) pfh.ProtocolEditor = NewProtocolEditor(prot)
pfh.Reference = prot pfh.Reference = prot
PPF.ProtocolMeta.SetProtocol(prot) pfh.name = prot.Metadata.Name
return err
}
func (pfh *ProtocolFileHandler) GetWorkarea() *fyne.Container {
return pfh.ProtocolEditor.Representation
} }
func (pfh *ProtocolFileHandler) Save() {
pfh.Changed = false func (pfh *ProtocolFileHandler) Name() string {
return pfh.name
} }
func (pfh *ProtocolFileHandler) GetWorkarea() *container.Scroll { func (pfh *ProtocolFileHandler) Path() string {
return container.NewVScroll(pfh.ProtocolEditor.Representation) return pfh.path
}
func (pfh *ProtocolFileHandler) Open(path string) error {
pfh.path = path
return pfh.Load()
}
func (pfh *ProtocolFileHandler) Save() error {
protocolctl.Save(pfh.Reference, pfh.path)
pfh.changed = false
return nil
}
func (pfh *ProtocolFileHandler) SaveAs(path string) error {
pfh.path = path
pfh.Save()
return nil
}
func (pfh *ProtocolFileHandler) Close() error {
return pfh.Save()
}
func (pfh *ProtocolFileHandler) SetChanged() {
pfh.changed = true
}
func (pfh *ProtocolFileHandler) HasChanged() bool {
return pfh.changed
}
func (pfh *ProtocolFileHandler) GetReference() interface{} {
return pfh.Reference
} }