186 lines
3.3 KiB
Go
186 lines
3.3 KiB
Go
package ui
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"fyne.io/fyne/v2"
|
|
"fyne.io/fyne/v2/container"
|
|
)
|
|
|
|
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 Controller,
|
|
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
|
|
}
|