package ui import ( "strings" "fyne.io/fyne/v2" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" ) // A Representationer provides a representation as fyne.Container type Representationer interface { Representation() *fyne.Container } // A FileHandler handles files in the application type FileHandler interface { Name() string Path() string Open(path string) error Save() error SaveAs(path string) error Close() error SetChanged() HasChanged() bool GetReference() interface{} } // A TabProvider gives back a container.TabItem and allows to set it for internal storage type TabProvider interface { SetTab(tab *container.TabItem) Tab() *container.TabItem } // ppfApp is the internal struct holding all the required main objects/elements for the application type ppfApp struct { App fyne.App Window fyne.Window // Container for the main layout, toolbar at top, in Center the doctabs. MainContainer *fyne.Container // toolbar Toolbar fyne.CanvasObject // left optional the local/remote library // tbd // center opened objects OpenTabs *container.DocTabs // DocTabs OpenObjects []FileHandler // actual files // Global important stuff Settings map[string]interface{} /*/ will be part of the Editor Metadata *Metadata Extensions *fyne.Container ContextBar *fyne.Container ContentTabs *fyne.Container Workarea *container.DocTabs // Once initialized metadata containers for swapping ProtocolMeta *ProtocolMetadata PacketMeta *PacketMetadata // Once initialized instances of the editor views EditorPacket *PacketEditor EditorProtocol *ProtocolEditor // workspace handling OpenProtocolFiles []*ProtocolFileHandler//*/ } // PPF is the global variable holding the application struct var PPF ppfApp // NewPPF is the entrypoint to create the application func NewPPF(fyneApp fyne.App, w fyne.Window) ppfApp { PPF.App = fyneApp PPF.Window = w PPF.Toolbar = CreateToolbar(fyneApp) PPF.OpenTabs = CreateWorkarea() return PPF } func (ppf *ppfApp) GetContainer() *fyne.Container { return container.NewBorder( ppf.Toolbar, //top nil, //bottom nil, //left // maybe Accordion with existing protocols, your protocols, your packets? nil, //right ppf.OpenTabs, ) } func (ppf *ppfApp) NewProtocolFile() { //TODO: show entry screen with choosable ways of: // PROTOCOL editor // create a new protocol // edit an existing protocol // PACKET editor // create a binary packet // edit an existing binary packet pfh := NewProtocolFileHandler() ppf.OpenObjects = append(ppf.OpenObjects, pfh) item := ppf.OpenTabs.Selected() item.Text = pfh.Name() item.Content = pfh.GetWorkarea() pfh.SetTab(item) } func (ppf *ppfApp) NewPacketFile() { } 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 } } pfh := NewProtocolFileHandler() pfh.Open(path) ppf.OpenObjects = append(ppf.OpenObjects, pfh) item := ppf.OpenTabs.Selected() item.Text = pfh.Path() item.Content = pfh.GetWorkarea() pfh.SetTab(item) } func (ppf *ppfApp) OpenPacketFile(path string) { } func (ppf *ppfApp) SaveFile(path string) { item := ppf.OpenTabs.Selected() for _, fh := range ppf.OpenObjects { if fh.(TabProvider).Tab() == item { fh.SaveAs(path) } } // if there exists another one with the same path, (max one!!!) /* // skip that check for now existingTab := -1 for i, v := range ppf.OpenTabs.Items { fmt.Printf("existing tab %d, path %s\n", 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 { toolbar := widget.NewToolbar() toolbar.Append(widget.NewToolbarAction(theme.ContentAddIcon(), func() { PPF.NewFile() })) toolbar.Append(widget.NewToolbarAction(theme.DocumentSaveIcon(), func() { if strings.HasPrefix(PPF.OpenTabs.Selected().Text, "*new") { dialog.NewFileSave(func(uri fyne.URIWriteCloser, err error) { if uri == nil { return } PPF.SaveFile(uri.URI().Path()) }, PPF.Window).Show() } else { PPF.SaveFile(PPF.OpenTabs.Selected().Text) } })) toolbar.Append(widget.NewToolbarAction(theme.StorageIcon(), func() { dialog.NewFileSave(func(uri fyne.URIWriteCloser, err error) { if uri == nil { return } PPF.SaveFile(uri.URI().Path()) }, PPF.Window).Show() })) toolbar.Append(widget.NewToolbarAction(theme.SettingsIcon(), func() { })) toolbar.Append(widget.NewToolbarSpacer()) toolbar.Append(widget.NewToolbarAction(theme.LogoutIcon(), func() { fyneApp.Quit() })) return toolbar } func CreateWorkarea() *container.DocTabs { tabs := container.NewDocTabs() tabs.OnClosed = func(ti *container.TabItem) { } tabs.OnSelected = func(ti *container.TabItem) { } return tabs }