diff --git a/internal/ui/main.go b/internal/ui/main.go index a7a5b21..69e3bb6 100644 --- a/internal/ui/main.go +++ b/internal/ui/main.go @@ -1,6 +1,7 @@ package ui import ( + "fmt" "strings" "fyne.io/fyne/v2" @@ -8,8 +9,6 @@ import ( "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" - "gitea.mmo.to/ProtocolPacketForger/ppf/protocol" - "gitea.mmo.to/ProtocolPacketForger/ppf/protocolctl" ) type Representationer interface { @@ -24,8 +23,10 @@ type FileHandler interface { SaveAs(path string) error Close() error - Changed() + SetChanged() HasChanged() bool + + GetReference() interface{} } type ppfApp struct { @@ -39,7 +40,7 @@ type ppfApp struct { // tbd // center opened objects OpenTabs *container.DocTabs // DocTabs - OpenObjects []*FileHandler // actual files + OpenObjects []FileHandler // actual files // Global important stuff Settings map[string]interface{} @@ -66,30 +67,20 @@ func NewPPF(fyneApp fyne.App, w fyne.Window) ppfApp { PPF.App = fyneApp PPF.Window = w PPF.Toolbar = CreateToolbar(fyneApp) - /*PPF.Workarea = CreateWorkarea() - PPF.Extensions = container.NewCenter() - PPF.ProtocolMeta = NewMetadataProtocol() - PPF.Metadata = &PPF.ProtocolMeta.Metadata - PPF.ContextBar = container.NewCenter() //*/ + PPF.OpenTabs = CreateWorkarea() return PPF } func (ppf *ppfApp) GetContainer() *fyne.Container { return container.NewBorder( - PPF.Toolbar, - nil, //PPF.ContextBar, - nil, //PPF.Metadata.Representation, - nil, //PPF.Extensions, - PPF.OpenTabs, + ppf.Toolbar, //top + nil, //bottom + nil, //left // maybe Accordion with existing protocols, your protocols, your packets? + nil, //right + 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() { //TODO: show entry screen with choosable ways of: // PROTOCOL editor @@ -99,32 +90,71 @@ func (ppf *ppfApp) NewProtocolFile() { // create a binary packet // edit an existing binary packet pfh := NewProtocolFileHandler() - PPF.OpenProtocolFiles = append(PPF.OpenProtocolFiles, pfh) - ppf.Workarea.Append(container.NewTabItem(pfh.Filename, pfh.GetWorkarea())) + ppf.OpenObjects = append(ppf.OpenObjects, pfh) + item := ppf.OpenTabs.Selected() + item.Text = pfh.Name() + item.Content = pfh.GetWorkarea() } func (ppf *ppfApp) NewPacketFile() { } -func (ppf *ppfApp) SaveFile(path string) { - item := ppf.Workarea.Selected() - for _, pfh := range ppf.OpenProtocolFiles { - if pfh.Filename == item.Text { - protocolctl.Save(pfh.ProtocolEditor.Reference, path) +func (ppf *ppfApp) OpenProtocolFile(path string) { + for _, v := range ppf.OpenTabs.Items { + if v.Text == path { + // do not open a file twice! + ppf.OpenTabs.Select(v) + return } } - item.Text = path - ppf.Workarea.Refresh() + pfh := NewProtocolFileHandler() + 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 { - for _, pfh := range ppf.OpenProtocolFiles { - if pfh.Filename == s { - return pfh.ProtocolEditor.Reference +func (ppf *ppfApp) OpenPacketFile(path string) { + +} + +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 { @@ -132,16 +162,8 @@ func CreateToolbar(fyneApp fyne.App) fyne.CanvasObject { toolbar.Append(widget.NewToolbarAction(theme.ContentAddIcon(), func() { 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() { - if strings.HasPrefix(PPF.Workarea.Selected().Text, "*new") { + if strings.HasPrefix(PPF.OpenTabs.Selected().Text, "*new") { dialog.NewFileSave(func(uri fyne.URIWriteCloser, err error) { if uri == nil { return @@ -149,7 +171,7 @@ func CreateToolbar(fyneApp fyne.App) fyne.CanvasObject { PPF.SaveFile(uri.URI().Path()) }, PPF.Window).Show() } else { - PPF.SaveFile(PPF.Workarea.Selected().Text) + PPF.SaveFile(PPF.OpenTabs.Selected().Text) } })) toolbar.Append(widget.NewToolbarAction(theme.StorageIcon(), func() { @@ -175,15 +197,9 @@ func CreateToolbar(fyneApp fyne.App) fyne.CanvasObject { func CreateWorkarea() *container.DocTabs { tabs := container.NewDocTabs() tabs.OnClosed = func(ti *container.TabItem) { - if len(tabs.Items) == 0 { - PPF.Metadata.Representation.Hide() - } + } 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 } diff --git a/internal/ui/newobjectdialog.go b/internal/ui/newobjectdialog.go index bd4104c..6fbe9aa 100644 --- a/internal/ui/newobjectdialog.go +++ b/internal/ui/newobjectdialog.go @@ -3,6 +3,8 @@ package ui import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/dialog" + "fyne.io/fyne/v2/storage" "fyne.io/fyne/v2/widget" ) @@ -20,34 +22,49 @@ func CreateNewObjectDialog() *NewObjectDialog { if pnod == nil { pnod = &NewObjectDialog{} - pnod.representation = container.NewMax(nil) // representation // grid layout 100x100px elements in a center layout, 4 buttons, new Protocol, edit protocol, new Packet, edit Packet - buttons := []widget.Button{} - buttons = append(buttons, *widget.NewButton("New protocol", func() { - PPF.NewProtocolFile() - })) - buttons = append(buttons, *widget.NewButton("Open/Edit protocol", func() { - pnod.representation.RemoveAll() - pnod.representation.Add(pnod.protocolChooser) - })) - buttons = append(buttons, *widget.NewButton("New packet", func() { - PPF.NewPacketFile() - })) - buttons = append(buttons, *widget.NewButton("Open/Edit packet", func() { - pnod.representation.RemoveAll() - pnod.representation.Add(pnod.packetChooser) - })) - selectgrid := container.NewGridWithColumns(2, nil) + buttons := []*widget.Button{ + widget.NewButton("New protocol", func() { + // 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 + PPF.NewProtocolFile() + }), + widget.NewButton("Open/Edit protocol", func() { + opendialog := dialog.NewFileOpen(func(uri fyne.URIReadCloser, err error) { + if uri == nil { + return + } + PPF.OpenProtocolFile(uri.URI().Path()) + }, PPF.Window) + opendialog.SetFilter(storage.NewExtensionFileFilter([]string{".protocoljson"})) + opendialog.Show() + }), + 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 { - selectgrid.Add(&v) + selectgrid.Add(v) } 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 // 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 // file chooser embedded // second tab -> own protocols, in a folder somewhere. diff --git a/internal/ui/protocoleditor.go b/internal/ui/protocoleditor.go index e796311..d3b3e85 100644 --- a/internal/ui/protocoleditor.go +++ b/internal/ui/protocoleditor.go @@ -11,21 +11,18 @@ import ( type ProtocolEditor struct { Representation *fyne.Container + FieldContainer *fyne.Container + Metadata *ProtocolMetadata Fields []*FieldEditor 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 { - container := container.NewGridWrap(fyne.NewSize(300, 400)) - protocolEditor := &ProtocolEditor{container, []*FieldEditor{}, ref} + metadata := NewMetadataProtocol() + 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() return protocolEditor } @@ -38,11 +35,14 @@ func (ed *ProtocolEditor) AddFieldCreator(fieldCreator *FieldEditor) { func (ed *ProtocolEditor) Redraw() { json := protocolctl.ToJson(ed.Reference) fmt.Printf("%s", json) - ed.Representation.RemoveAll() + ed.FieldContainer.RemoveAll() + // existing fields 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 { - ed.Representation.Add(GetAdder(ed)) + ed.FieldContainer.Add(GetAdder(ed)) } + // Metadata + ed.Metadata.SetProtocol(ed.Reference) } diff --git a/internal/ui/protocolfilehandler.go b/internal/ui/protocolfilehandler.go index 2820d43..0a6aa30 100644 --- a/internal/ui/protocolfilehandler.go +++ b/internal/ui/protocolfilehandler.go @@ -1,48 +1,75 @@ package ui import ( - "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2" "gitea.mmo.to/ProtocolPacketForger/ppf/protocol" "gitea.mmo.to/ProtocolPacketForger/ppf/protocolctl" ) +// implements FileHandler type ProtocolFileHandler struct { ProtocolEditor *ProtocolEditor - Filename string - Changed bool + name string + path string + changed bool Reference *protocol.ProtocolStructure } func NewProtocolFileHandler() *ProtocolFileHandler { pfh := ProtocolFileHandler{} - pfh.Filename = "*new" - pfh.Changed = true - pfh.ProtocolEditor = GetProtocolEditor() + pfh.name = "*new" + pfh.changed = true + pfh.ProtocolEditor = NewProtocolEditor(protocolctl.NewProtocolStructure()) return &pfh } -func LoadProtocolFileHandler(path string) *ProtocolFileHandler { - pfh := ProtocolFileHandler{} - pfh.Filename = path - pfh.Load() - return &pfh -} - -func (pfh *ProtocolFileHandler) Load() { - prot, err := protocolctl.LoadNew(pfh.Filename) +func (pfh *ProtocolFileHandler) Load() error { + prot, err := protocolctl.LoadNew(pfh.Path()) if err != nil { // process error err = nil } pfh.ProtocolEditor = NewProtocolEditor(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 { - return container.NewVScroll(pfh.ProtocolEditor.Representation) +func (pfh *ProtocolFileHandler) Path() string { + 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 }