package ui import ( "sync" "fyne.io/fyne/v2" "fyne.io/fyne/v2/container" ) // TODO: Implement screen reading from file! type TabbedView struct { *BaseView // The array of child views tabViews []View // The current active view currentTabView View // The tabs tabs *container.AppTabs // The location of teh tabs in the view tabLocation container.TabLocation mu sync.Mutex } // NewTabbedView creates a new tabbed view func NewTabbedView( controller ViewModel, tabLocation container.TabLocation, tabview ...View, ) *TabbedView { v := new(TabbedView) v.BaseView = NewBaseView(v, controller) v.tabViews = tabview v.tabLocation = tabLocation return v } func (v *TabbedView) Initialize() fyne.CanvasObject { v.buildUI() return v.BaseView.Initialize() } func (v *TabbedView) OnShow() { v.BaseView.OnShow() if v.currentTabView != nil { v.currentTabView.OnShow() } } func (v *TabbedView) OnHide() { if v.currentTabView != nil { v.currentTabView.OnHide() } v.BaseView.OnHide() } func (v *TabbedView) Refresh() { if v.currentTabView != nil { v.currentTabView.Refresh() } v.BaseView.Refresh() } func (v *TabbedView) Append(tabview ...View) { v.mu.Lock() defer v.mu.Unlock() v.tabViews = append(v.tabViews, tabview...) for _, tv := range tabview { v.tabs.Append(container.NewTabItem( tv.Title(), tv.Initialize())) } } func (v *TabbedView) RemoveActive() { currIdx := v.tabs.SelectedIndex() v.Remove(currIdx) } func (v *TabbedView) Remove(idx int) { if idx < 0 || idx >= len(v.tabViews) { return } curIdx := v.tabs.SelectedIndex() isCurrent := (curIdx == idx) && (v.currentTabView != nil) v.mu.Lock() defer v.mu.Unlock() if isCurrent { v.currentTabView.OnHide() v.currentTabView = nil } v.tabViews = append(v.tabViews[0:curIdx], v.tabViews[curIdx+1:]...) v.tabs.RemoveIndex(idx) if isCurrent { if idx > 0 { idx = idx - 1 } if idx < len(v.tabViews) { v.tabs.SelectIndex(curIdx) } } } func (v *TabbedView) NumTabs() int { return len(v.tabViews) } func (v *TabbedView) TabIndex(view View) int { for idx, tv := range v.tabViews { if tv.Equals(view) { return idx } } return -1 } func (v *TabbedView) SelectTabIndex(index int) { v.tabs.SelectIndex(index) } func (v *TabbedView) SelectTab(view View) { v.SelectTabIndex(v.TabIndex(view)) } func (v *TabbedView) buildUI() { v.tabs = container.NewAppTabs() v.tabs.SetTabLocation(v.tabLocation) v.tabs.OnSelected = func(tab *container.TabItem) { LogWindowEventMessage( v, OnTabSelected, "Selected tab: %s", tab.Text, ) go func() { v.mu.Lock() defer v.mu.Unlock() idx := v.tabs.SelectedIndex() if idx < 0 || idx >= len(v.tabViews) { return } v.currentTabView = v.tabViews[idx] v.currentTabView.OnShow() }() } v.tabs.OnUnselected = func(tab *container.TabItem) { LogWindowEventMessage( v, OnTabUnselected, "Unselected tab: %s", tab.Text, ) go func() { v.mu.Lock() defer v.mu.Unlock() idx := v.tabs.SelectedIndex() if idx < 0 || idx >= len(v.tabViews) { return } if v.currentTabView != nil && v.currentTabView.Equals(v.tabViews[idx]) { v.currentTabView.OnHide() v.currentTabView = nil } }() } for _, tv := range v.tabViews { v.tabs.Append(container.NewTabItem(tv.Title(), tv.Initialize())) } if len(v.tabViews) > 0 { v.currentTabView = v.tabViews[0] } v.CanvasObject = v.tabs }