Refactor: extract Toolbar from BrowsingPane as its own component
This commit is contained in:
+26
-134
@@ -3,17 +3,12 @@ package browsing
|
|||||||
import (
|
import (
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
"fyne.io/fyne/v2/lang"
|
|
||||||
"fyne.io/fyne/v2/layout"
|
"fyne.io/fyne/v2/layout"
|
||||||
"fyne.io/fyne/v2/theme"
|
|
||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
"github.com/dweymouth/supersonic/backend"
|
"github.com/dweymouth/supersonic/backend"
|
||||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||||
"github.com/dweymouth/supersonic/ui/controller"
|
"github.com/dweymouth/supersonic/ui/controller"
|
||||||
"github.com/dweymouth/supersonic/ui/layouts"
|
|
||||||
myTheme "github.com/dweymouth/supersonic/ui/theme"
|
myTheme "github.com/dweymouth/supersonic/ui/theme"
|
||||||
|
|
||||||
ttwidget "github.com/dweymouth/fyne-tooltip/widget"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Page interface {
|
type Page interface {
|
||||||
@@ -60,60 +55,25 @@ type CanShowPlayQueue interface {
|
|||||||
type BrowsingPane struct {
|
type BrowsingPane struct {
|
||||||
widget.BaseWidget
|
widget.BaseWidget
|
||||||
|
|
||||||
app *backend.App
|
OnHistoryChanged func()
|
||||||
|
|
||||||
|
playbackManager *backend.PlaybackManager
|
||||||
|
|
||||||
curPage Page
|
curPage Page
|
||||||
|
|
||||||
home *ttwidget.Button
|
|
||||||
forward *ttwidget.Button
|
|
||||||
back *ttwidget.Button
|
|
||||||
reload *ttwidget.Button
|
|
||||||
history []SavedPage
|
history []SavedPage
|
||||||
historyIdx int
|
historyIdx int
|
||||||
|
|
||||||
settingsBtn *ttwidget.Button
|
|
||||||
settingsMenu *fyne.Menu
|
|
||||||
navBtnsContainer *fyne.Container
|
|
||||||
pageContainer *fyne.Container
|
pageContainer *fyne.Container
|
||||||
container *fyne.Container
|
|
||||||
navBtnsPageMap map[controller.PageName]fyne.Resource
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBrowsingPane(app *backend.App, contr *controller.Controller, onGoHome func()) *BrowsingPane {
|
func NewBrowsingPane(app *backend.PlaybackManager, contr *controller.Controller, onGoHome func()) *BrowsingPane {
|
||||||
b := &BrowsingPane{app: app}
|
b := &BrowsingPane{playbackManager: app}
|
||||||
b.ExtendBaseWidget(b)
|
b.ExtendBaseWidget(b)
|
||||||
b.home = ttwidget.NewButtonWithIcon("", theme.HomeIcon(), onGoHome)
|
b.playbackManager.OnSongChange(b.onSongChange)
|
||||||
b.home.SetToolTip(lang.L("Home"))
|
b.playbackManager.OnPlayTimeUpdate(b.onPlayTimeUpdate)
|
||||||
b.back = ttwidget.NewButtonWithIcon("", theme.NavigateBackIcon(), b.GoBack)
|
b.playbackManager.OnQueueChange(b.onQueueChange)
|
||||||
b.back.SetToolTip(lang.L("Back"))
|
|
||||||
b.forward = ttwidget.NewButtonWithIcon("", theme.NavigateNextIcon(), b.GoForward)
|
|
||||||
b.forward.SetToolTip(lang.L("Forward"))
|
|
||||||
b.reload = ttwidget.NewButtonWithIcon("", theme.ViewRefreshIcon(), b.Reload)
|
|
||||||
b.reload.SetToolTip(lang.L("Reload"))
|
|
||||||
b.app.PlaybackManager.OnSongChange(b.onSongChange)
|
|
||||||
b.app.PlaybackManager.OnPlayTimeUpdate(b.onPlayTimeUpdate)
|
|
||||||
b.app.PlaybackManager.OnQueueChange(b.onQueueChange)
|
|
||||||
bkgrnd := myTheme.NewThemedRectangle(myTheme.ColorNamePageBackground)
|
bkgrnd := myTheme.NewThemedRectangle(myTheme.ColorNamePageBackground)
|
||||||
b.pageContainer = container.NewStack(bkgrnd, layout.NewSpacer())
|
b.pageContainer = container.NewStack(bkgrnd, layout.NewSpacer())
|
||||||
b.settingsBtn = ttwidget.NewButtonWithIcon("", theme.SettingsIcon(), func() {
|
|
||||||
p := widget.NewPopUpMenu(b.settingsMenu,
|
|
||||||
fyne.CurrentApp().Driver().CanvasForObject(b.settingsBtn))
|
|
||||||
p.ShowAtPosition(fyne.NewPos(b.Size().Width-p.MinSize().Width+4,
|
|
||||||
b.navBtnsContainer.MinSize().Height+theme.Padding()))
|
|
||||||
})
|
|
||||||
b.settingsBtn.SetToolTip(lang.L("Menu"))
|
|
||||||
quickSearchBtn := ttwidget.NewButtonWithIcon("", theme.SearchIcon(), contr.ShowQuickSearch)
|
|
||||||
quickSearchBtn.SetToolTip(lang.L("Search Everywhere"))
|
|
||||||
b.settingsMenu = fyne.NewMenu("")
|
|
||||||
b.navBtnsContainer = container.NewHBox()
|
|
||||||
b.navBtnsPageMap = map[controller.PageName]fyne.Resource{}
|
|
||||||
b.container = container.NewBorder(container.New(
|
|
||||||
&layout.CustomPaddedLayout{LeftPadding: -5, RightPadding: -5},
|
|
||||||
container.New(layouts.NewLeftMiddleRightLayout(0, 0),
|
|
||||||
container.NewHBox(b.home, b.back, b.forward, b.reload), b.navBtnsContainer,
|
|
||||||
container.NewHBox(layout.NewSpacer(), quickSearchBtn, b.settingsBtn))),
|
|
||||||
nil, nil, nil, b.pageContainer)
|
|
||||||
b.updateHistoryButtons()
|
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,77 +84,19 @@ func (b *BrowsingPane) SetPage(p Page) {
|
|||||||
b.pageContainer.Objects[1] = layout.NewSpacer()
|
b.pageContainer.Objects[1] = layout.NewSpacer()
|
||||||
b.curPage = nil
|
b.curPage = nil
|
||||||
b.pageContainer.Refresh()
|
b.pageContainer.Refresh()
|
||||||
b.updateNavBtnsColor(p)
|
|
||||||
} else {
|
} else {
|
||||||
oldPage := b.curPage
|
oldPage := b.curPage
|
||||||
if b.doSetPage(p) && oldPage != nil {
|
if b.doSetPage(p) && oldPage != nil {
|
||||||
b.addPageToHistory(oldPage, true)
|
b.addPageToHistory(oldPage, true)
|
||||||
b.updateHistoryButtons()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
b.onHistoryChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BrowsingPane) ClearHistory() {
|
func (b *BrowsingPane) ClearHistory() {
|
||||||
b.history = nil
|
b.history = nil
|
||||||
b.historyIdx = 0
|
b.historyIdx = 0
|
||||||
b.updateHistoryButtons()
|
b.onHistoryChanged()
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BrowsingPane) AddSettingsMenuItem(label string, icon fyne.Resource, action func()) {
|
|
||||||
item := fyne.NewMenuItem(label, action)
|
|
||||||
item.Icon = icon
|
|
||||||
b.settingsMenu.Items = append(b.settingsMenu.Items, item)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BrowsingPane) AddSettingsSubmenu(label string, icon fyne.Resource, menu *fyne.Menu) {
|
|
||||||
item := fyne.NewMenuItem(label, nil)
|
|
||||||
item.ChildMenu = menu
|
|
||||||
item.Icon = icon
|
|
||||||
b.settingsMenu.Items = append(b.settingsMenu.Items, item)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BrowsingPane) SetSubmenuForMenuItem(label string, submenu *fyne.Menu) {
|
|
||||||
for _, item := range b.settingsMenu.Items {
|
|
||||||
if item.Label == label {
|
|
||||||
item.ChildMenu = submenu
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BrowsingPane) AddSettingsMenuSeparator() {
|
|
||||||
b.settingsMenu.Items = append(b.settingsMenu.Items,
|
|
||||||
fyne.NewMenuItemSeparator())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BrowsingPane) AddNavigationButton(icon fyne.Resource, pageName controller.PageName, action func()) *ttwidget.Button {
|
|
||||||
// make a copy of the icon, because it can change the color
|
|
||||||
browsingPaneIcon := theme.NewThemedResource(icon)
|
|
||||||
btn := ttwidget.NewButtonWithIcon("", browsingPaneIcon, action)
|
|
||||||
btn.SetToolTip(lang.L(pageName.String()))
|
|
||||||
b.navBtnsContainer.Add(btn)
|
|
||||||
b.navBtnsPageMap[pageName] = browsingPaneIcon
|
|
||||||
return btn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BrowsingPane) DisableNavigationButtons() {
|
|
||||||
for _, obj := range b.navBtnsContainer.Objects {
|
|
||||||
obj.(fyne.Disableable).Disable()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BrowsingPane) EnableNavigationButtons() {
|
|
||||||
for _, obj := range b.navBtnsContainer.Objects {
|
|
||||||
obj.(fyne.Disableable).Enable()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BrowsingPane) ActivateNavigationButton(num int) {
|
|
||||||
if num < len(b.navBtnsContainer.Objects) {
|
|
||||||
btn := b.navBtnsContainer.Objects[num].(*widget.Button)
|
|
||||||
if !btn.Disabled() && !btn.Hidden {
|
|
||||||
btn.OnTapped()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BrowsingPane) GetSearchBarIfAny() fyne.Focusable {
|
func (b *BrowsingPane) GetSearchBarIfAny() fyne.Focusable {
|
||||||
@@ -255,15 +157,20 @@ func (b *BrowsingPane) doSetPage(p Page) bool {
|
|||||||
b.curPage = p
|
b.curPage = p
|
||||||
if np, ok := p.(CanShowNowPlaying); ok {
|
if np, ok := p.(CanShowNowPlaying); ok {
|
||||||
// inform page of currently playing track
|
// inform page of currently playing track
|
||||||
np.OnSongChange(b.app.PlaybackManager.NowPlaying(), nil)
|
np.OnSongChange(b.playbackManager.NowPlaying(), nil)
|
||||||
}
|
}
|
||||||
b.pageContainer.Remove(b.curPage)
|
b.pageContainer.Remove(b.curPage)
|
||||||
b.pageContainer.Objects[1] = p
|
b.pageContainer.Objects[1] = p
|
||||||
b.updateNavBtnsColor(p)
|
|
||||||
b.Refresh()
|
b.Refresh()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *BrowsingPane) onHistoryChanged() {
|
||||||
|
if b.OnHistoryChanged != nil {
|
||||||
|
b.OnHistoryChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (b *BrowsingPane) onSongChange(song mediaprovider.MediaItem, lastScrobbledIfAny *mediaprovider.Track) {
|
func (b *BrowsingPane) onSongChange(song mediaprovider.MediaItem, lastScrobbledIfAny *mediaprovider.Track) {
|
||||||
fyne.Do(func() {
|
fyne.Do(func() {
|
||||||
if b.curPage == nil {
|
if b.curPage == nil {
|
||||||
@@ -313,17 +220,12 @@ func (b *BrowsingPane) addPageToHistory(p Page, truncate bool) {
|
|||||||
b.historyIdx++
|
b.historyIdx++
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BrowsingPane) updateHistoryButtons() {
|
func (b *BrowsingPane) CanGoBack() bool {
|
||||||
if b.historyIdx > 0 {
|
return b.historyIdx > 0
|
||||||
b.back.Enable()
|
}
|
||||||
} else {
|
|
||||||
b.back.Disable()
|
func (b *BrowsingPane) CanGoForward() bool {
|
||||||
}
|
return b.historyIdx < len(b.history)-1
|
||||||
if b.historyIdx < len(b.history)-1 {
|
|
||||||
b.forward.Enable()
|
|
||||||
} else {
|
|
||||||
b.forward.Disable()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BrowsingPane) GoBack() {
|
func (b *BrowsingPane) GoBack() {
|
||||||
@@ -334,7 +236,7 @@ func (b *BrowsingPane) GoBack() {
|
|||||||
b.addPageToHistory(b.curPage, false)
|
b.addPageToHistory(b.curPage, false)
|
||||||
b.historyIdx -= 2
|
b.historyIdx -= 2
|
||||||
b.doSetPage(p)
|
b.doSetPage(p)
|
||||||
b.updateHistoryButtons()
|
b.onHistoryChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,7 +245,7 @@ func (b *BrowsingPane) GoForward() {
|
|||||||
p := b.history[b.historyIdx+1].Restore()
|
p := b.history[b.historyIdx+1].Restore()
|
||||||
b.addPageToHistory(b.curPage, false)
|
b.addPageToHistory(b.curPage, false)
|
||||||
b.doSetPage(p)
|
b.doSetPage(p)
|
||||||
b.updateHistoryButtons()
|
b.onHistoryChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,15 +263,5 @@ func (b *BrowsingPane) CurrentPage() controller.Route {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *BrowsingPane) CreateRenderer() fyne.WidgetRenderer {
|
func (b *BrowsingPane) CreateRenderer() fyne.WidgetRenderer {
|
||||||
return widget.NewSimpleRenderer(b.container)
|
return widget.NewSimpleRenderer(b.pageContainer)
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BrowsingPane) updateNavBtnsColor(p Page) {
|
|
||||||
for pageName, icon := range b.navBtnsPageMap {
|
|
||||||
if p != nil && pageName == p.Route().Page {
|
|
||||||
icon.(*theme.ThemedResource).ColorName = theme.ColorNamePrimary
|
|
||||||
} else {
|
|
||||||
icon.(*theme.ThemedResource).ColorName = theme.ColorNameForeground
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-53
@@ -24,6 +24,7 @@ import (
|
|||||||
"fyne.io/fyne/v2/dialog"
|
"fyne.io/fyne/v2/dialog"
|
||||||
"fyne.io/fyne/v2/driver/desktop"
|
"fyne.io/fyne/v2/driver/desktop"
|
||||||
"fyne.io/fyne/v2/lang"
|
"fyne.io/fyne/v2/lang"
|
||||||
|
"fyne.io/fyne/v2/layout"
|
||||||
"fyne.io/fyne/v2/theme"
|
"fyne.io/fyne/v2/theme"
|
||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
)
|
)
|
||||||
@@ -35,6 +36,7 @@ type MainWindow struct {
|
|||||||
Router browsing.Router
|
Router browsing.Router
|
||||||
Controller *controller.Controller
|
Controller *controller.Controller
|
||||||
BrowsingPane *browsing.BrowsingPane
|
BrowsingPane *browsing.BrowsingPane
|
||||||
|
Toolbar *Toolbar
|
||||||
BottomPanel *BottomPanel
|
BottomPanel *BottomPanel
|
||||||
ToastOverlay *ToastOverlay
|
ToastOverlay *ToastOverlay
|
||||||
|
|
||||||
@@ -43,9 +45,6 @@ type MainWindow struct {
|
|||||||
alreadyConnected bool // tracks if we have already connected to a server before
|
alreadyConnected bool // tracks if we have already connected to a server before
|
||||||
content *mainWindowContent
|
content *mainWindowContent
|
||||||
|
|
||||||
// needs to be shown/hidden when switching between servers based on whether they support radio
|
|
||||||
radioBtn fyne.CanvasObject
|
|
||||||
|
|
||||||
// updated when changing servers or libraries
|
// updated when changing servers or libraries
|
||||||
librarySubmenu *fyne.Menu
|
librarySubmenu *fyne.Menu
|
||||||
}
|
}
|
||||||
@@ -66,9 +65,12 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string,
|
|||||||
m.SetupSystemTrayMenu(displayAppName, fyneApp)
|
m.SetupSystemTrayMenu(displayAppName, fyneApp)
|
||||||
}
|
}
|
||||||
m.Controller = controller.New(app, appVersion, m.Window)
|
m.Controller = controller.New(app, appVersion, m.Window)
|
||||||
m.BrowsingPane = browsing.NewBrowsingPane(app, m.Controller, func() { m.Router.NavigateTo(m.StartupPage()) })
|
m.BrowsingPane = browsing.NewBrowsingPane(app.PlaybackManager, m.Controller, func() { m.Router.NavigateTo(m.StartupPage()) })
|
||||||
m.ToastOverlay = NewToastOverlay()
|
m.ToastOverlay = NewToastOverlay()
|
||||||
m.Router = browsing.NewRouter(app, m.Controller, m.BrowsingPane)
|
m.Router = browsing.NewRouter(app, m.Controller, m.BrowsingPane)
|
||||||
|
goHomeFn := func() { m.Router.NavigateTo(m.StartupPage()) }
|
||||||
|
m.Toolbar = NewToolbar(m.BrowsingPane, m.Router.NavigateTo, goHomeFn, m.Controller.ShowQuickSearch)
|
||||||
|
|
||||||
// inject controller dependencies
|
// inject controller dependencies
|
||||||
m.Controller.NavHandler = m.Router.NavigateTo
|
m.Controller.NavHandler = m.Router.NavigateTo
|
||||||
m.Controller.ReloadFunc = m.BrowsingPane.Reload
|
m.Controller.ReloadFunc = m.BrowsingPane.Reload
|
||||||
@@ -98,23 +100,23 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string,
|
|||||||
go m.RunOnServerConnectedTasks(conf, app, displayAppName)
|
go m.RunOnServerConnectedTasks(conf, app, displayAppName)
|
||||||
})
|
})
|
||||||
app.ServerManager.OnLogout(func() {
|
app.ServerManager.OnLogout(func() {
|
||||||
m.BrowsingPane.DisableNavigationButtons()
|
m.Toolbar.DisableNavigationButtons()
|
||||||
m.BrowsingPane.SetPage(nil)
|
m.BrowsingPane.SetPage(nil)
|
||||||
m.BrowsingPane.ClearHistory()
|
m.BrowsingPane.ClearHistory()
|
||||||
m.Controller.PromptForLoginAndConnect()
|
m.Controller.PromptForLoginAndConnect()
|
||||||
})
|
})
|
||||||
m.BrowsingPane.AddSettingsMenuItem(lang.L("Log Out"), theme.LogoutIcon(), func() { app.ServerManager.Logout(true) })
|
m.Toolbar.AddSettingsMenuItem(lang.L("Log Out"), theme.LogoutIcon(), func() { app.ServerManager.Logout(true) })
|
||||||
m.BrowsingPane.AddSettingsMenuItem(lang.L("Switch Servers"), theme.LoginIcon(), func() { app.ServerManager.Logout(false) })
|
m.Toolbar.AddSettingsMenuItem(lang.L("Switch Servers"), theme.LoginIcon(), func() { app.ServerManager.Logout(false) })
|
||||||
m.BrowsingPane.AddSettingsSubmenu(lang.L("Select Library"), myTheme.LibraryIcon, fyne.NewMenu("",
|
m.Toolbar.AddSettingsSubmenu(lang.L("Select Library"), myTheme.LibraryIcon, fyne.NewMenu("",
|
||||||
fyne.NewMenuItem(lang.L("All Libraries"), func() { /* dummy - will get replaced on server login */ })))
|
fyne.NewMenuItem(lang.L("All Libraries"), func() { /* dummy - will get replaced on server login */ })))
|
||||||
m.BrowsingPane.AddSettingsMenuItem(lang.L("Rescan Library"), theme.ViewRefreshIcon(), func() { app.ServerManager.Server.RescanLibrary() })
|
m.Toolbar.AddSettingsMenuItem(lang.L("Rescan Library"), theme.ViewRefreshIcon(), func() { app.ServerManager.Server.RescanLibrary() })
|
||||||
m.BrowsingPane.AddSettingsMenuSeparator()
|
m.Toolbar.AddSettingsMenuSeparator()
|
||||||
m.BrowsingPane.AddSettingsSubmenu(lang.L("Visualizations"), myTheme.VisualizationIcon,
|
m.Toolbar.AddSettingsSubmenu(lang.L("Visualizations"), myTheme.VisualizationIcon,
|
||||||
fyne.NewMenu("", []*fyne.MenuItem{
|
fyne.NewMenu("", []*fyne.MenuItem{
|
||||||
fyne.NewMenuItem(lang.L("Peak Meter"), m.Controller.ShowPeakMeter),
|
fyne.NewMenuItem(lang.L("Peak Meter"), m.Controller.ShowPeakMeter),
|
||||||
}...))
|
}...))
|
||||||
m.BrowsingPane.AddSettingsMenuSeparator()
|
m.Toolbar.AddSettingsMenuSeparator()
|
||||||
m.BrowsingPane.AddSettingsMenuItem(lang.L("Check for Updates"), theme.DownloadIcon(), func() {
|
m.Toolbar.AddSettingsMenuItem(lang.L("Check for Updates"), theme.DownloadIcon(), func() {
|
||||||
go func() {
|
go func() {
|
||||||
if t := app.UpdateChecker.CheckLatestVersionTag(); t != "" && t != app.VersionTag() {
|
if t := app.UpdateChecker.CheckLatestVersionTag(); t != "" && t != app.VersionTag() {
|
||||||
fyne.Do(func() { m.ShowNewVersionDialog(displayAppName, t) })
|
fyne.Do(func() { m.ShowNewVersionDialog(displayAppName, t) })
|
||||||
@@ -127,14 +129,15 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string,
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
})
|
})
|
||||||
m.BrowsingPane.AddSettingsMenuItem(lang.L("Settings")+"...", theme.SettingsIcon(), m.showSettingsDialog)
|
m.Toolbar.AddSettingsMenuItem(lang.L("Settings")+"...", theme.SettingsIcon(), m.showSettingsDialog)
|
||||||
m.BrowsingPane.AddSettingsMenuItem(lang.L("About")+"...", theme.InfoIcon(), m.Controller.ShowAboutDialog)
|
m.Toolbar.AddSettingsMenuItem(lang.L("About")+"...", theme.InfoIcon(), m.Controller.ShowAboutDialog)
|
||||||
m.addNavigationButtons()
|
m.Toolbar.DisableNavigationButtons()
|
||||||
m.BrowsingPane.DisableNavigationButtons()
|
|
||||||
m.addShortcuts()
|
m.addShortcuts()
|
||||||
|
|
||||||
center := container.NewStack(m.BrowsingPane, m.ToastOverlay)
|
center := container.NewStack(m.BrowsingPane, m.ToastOverlay)
|
||||||
m.content = newMainWindowContent(container.NewBorder(nil, m.BottomPanel, nil, nil, center),
|
toolbarWrapper := container.New(
|
||||||
|
&layout.CustomPaddedLayout{LeftPadding: -theme.Padding(), RightPadding: -theme.Padding()}, m.Toolbar)
|
||||||
|
m.content = newMainWindowContent(container.NewBorder(toolbarWrapper, m.BottomPanel, nil, nil, center),
|
||||||
m.Controller.UnselectAll)
|
m.Controller.UnselectAll)
|
||||||
m.Window.SetContent(fynetooltip.AddWindowToolTipLayer(m.content, m.Window.Canvas()))
|
m.Window.SetContent(fynetooltip.AddWindowToolTipLayer(m.content, m.Window.Canvas()))
|
||||||
m.setInitialSize()
|
m.setInitialSize()
|
||||||
@@ -285,24 +288,20 @@ func (m *MainWindow) RunOnServerConnectedTasks(serverConf *backend.ServerConfig,
|
|||||||
}
|
}
|
||||||
m.librarySubmenu = libraryMenu
|
m.librarySubmenu = libraryMenu
|
||||||
m.librarySubmenu.Items[initialLibraryMenuIdx].Checked = true
|
m.librarySubmenu.Items[initialLibraryMenuIdx].Checked = true
|
||||||
m.BrowsingPane.SetSubmenuForMenuItem(lang.L("Select Library"), libraryMenu)
|
m.Toolbar.SetSubmenuForMenuItem(lang.L("Select Library"), libraryMenu)
|
||||||
|
|
||||||
if initialLibraryID != "" {
|
if initialLibraryID != "" {
|
||||||
m.App.ServerManager.Server.SetLibrary(initialLibraryID)
|
m.App.ServerManager.Server.SetLibrary(initialLibraryID)
|
||||||
}
|
}
|
||||||
|
|
||||||
fyne.Do(func() {
|
fyne.Do(func() {
|
||||||
m.BrowsingPane.EnableNavigationButtons()
|
m.Toolbar.EnableNavigationButtons()
|
||||||
m.Router.NavigateTo(m.StartupPage())
|
m.Router.NavigateTo(m.StartupPage())
|
||||||
_, canRate := m.App.ServerManager.Server.(mediaprovider.SupportsRating)
|
_, canRate := m.App.ServerManager.Server.(mediaprovider.SupportsRating)
|
||||||
m.BottomPanel.NowPlaying.DisableRating = !canRate
|
m.BottomPanel.NowPlaying.DisableRating = !canRate
|
||||||
|
|
||||||
_, supportsRadio := m.App.ServerManager.Server.(mediaprovider.RadioProvider)
|
_, supportsRadio := m.App.ServerManager.Server.(mediaprovider.RadioProvider)
|
||||||
if supportsRadio {
|
m.Toolbar.SetRadioButtonVisible(supportsRadio)
|
||||||
m.radioBtn.Show()
|
|
||||||
} else {
|
|
||||||
m.radioBtn.Hide()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
m.App.SaveConfigFile()
|
m.App.SaveConfigFile()
|
||||||
@@ -395,33 +394,6 @@ func (m *MainWindow) ShowWhatsNewDialog() {
|
|||||||
dialog.ShowCustom("What's new in "+res.AppVersion, lang.L("Close"), dialogs.NewWhatsNewDialog(), m.Window)
|
dialog.ShowCustom("What's new in "+res.AppVersion, lang.L("Close"), dialogs.NewWhatsNewDialog(), m.Window)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MainWindow) addNavigationButtons() {
|
|
||||||
m.BrowsingPane.AddNavigationButton(myTheme.NowPlayingIcon, controller.NowPlaying, func() {
|
|
||||||
m.Router.NavigateTo(controller.NowPlayingRoute())
|
|
||||||
})
|
|
||||||
m.BrowsingPane.AddNavigationButton(myTheme.FavoriteIcon, controller.Favorites, func() {
|
|
||||||
m.Router.NavigateTo(controller.FavoritesRoute())
|
|
||||||
})
|
|
||||||
m.BrowsingPane.AddNavigationButton(myTheme.AlbumIcon, controller.Albums, func() {
|
|
||||||
m.Router.NavigateTo(controller.AlbumsRoute())
|
|
||||||
})
|
|
||||||
m.BrowsingPane.AddNavigationButton(myTheme.ArtistIcon, controller.Artists, func() {
|
|
||||||
m.Router.NavigateTo(controller.ArtistsRoute())
|
|
||||||
})
|
|
||||||
m.BrowsingPane.AddNavigationButton(myTheme.GenreIcon, controller.Genres, func() {
|
|
||||||
m.Router.NavigateTo(controller.GenresRoute())
|
|
||||||
})
|
|
||||||
m.BrowsingPane.AddNavigationButton(myTheme.PlaylistIcon, controller.Playlists, func() {
|
|
||||||
m.Router.NavigateTo(controller.PlaylistsRoute())
|
|
||||||
})
|
|
||||||
m.BrowsingPane.AddNavigationButton(myTheme.TracksIcon, controller.Tracks, func() {
|
|
||||||
m.Router.NavigateTo(controller.TracksRoute())
|
|
||||||
})
|
|
||||||
m.radioBtn = m.BrowsingPane.AddNavigationButton(myTheme.RadioIcon, controller.Radios, func() {
|
|
||||||
m.Router.NavigateTo(controller.RadiosRoute())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MainWindow) addShortcuts() {
|
func (m *MainWindow) addShortcuts() {
|
||||||
for _, sh := range shortcuts.BackShortcuts {
|
for _, sh := range shortcuts.BackShortcuts {
|
||||||
m.Canvas().AddShortcut(&sh, func(_ fyne.Shortcut) {
|
m.Canvas().AddShortcut(&sh, func(_ fyne.Shortcut) {
|
||||||
@@ -473,7 +445,7 @@ func (m *MainWindow) addShortcuts() {
|
|||||||
for i, ns := range shortcuts.NavShortcuts {
|
for i, ns := range shortcuts.NavShortcuts {
|
||||||
m.Canvas().AddShortcut(&ns, func(i int) func(fyne.Shortcut) {
|
m.Canvas().AddShortcut(&ns, func(i int) func(fyne.Shortcut) {
|
||||||
return func(fyne.Shortcut) {
|
return func(fyne.Shortcut) {
|
||||||
m.BrowsingPane.ActivateNavigationButton(i)
|
m.Toolbar.ActivateNavigationButton(i)
|
||||||
}
|
}
|
||||||
}(i))
|
}(i))
|
||||||
}
|
}
|
||||||
|
|||||||
+203
@@ -0,0 +1,203 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/lang"
|
||||||
|
"fyne.io/fyne/v2/layout"
|
||||||
|
"fyne.io/fyne/v2/theme"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
|
"github.com/dweymouth/supersonic/ui/browsing"
|
||||||
|
"github.com/dweymouth/supersonic/ui/controller"
|
||||||
|
"github.com/dweymouth/supersonic/ui/layouts"
|
||||||
|
myTheme "github.com/dweymouth/supersonic/ui/theme"
|
||||||
|
|
||||||
|
ttwidget "github.com/dweymouth/fyne-tooltip/widget"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Toolbar struct {
|
||||||
|
widget.BaseWidget
|
||||||
|
|
||||||
|
browsingPane *browsing.BrowsingPane
|
||||||
|
|
||||||
|
home *ttwidget.Button
|
||||||
|
forward *ttwidget.Button
|
||||||
|
back *ttwidget.Button
|
||||||
|
reload *ttwidget.Button
|
||||||
|
|
||||||
|
navBtnsContainer *fyne.Container
|
||||||
|
navBtnsPageMap map[controller.PageName]fyne.Resource
|
||||||
|
radioBtn fyne.CanvasObject
|
||||||
|
|
||||||
|
quickSearchBtn *ttwidget.Button
|
||||||
|
settingsBtn *ttwidget.Button
|
||||||
|
settingsMenu *fyne.Menu
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewToolbar(browsingPane *browsing.BrowsingPane, navigateFn func(controller.Route), homeFunc, showSearchFn func()) *Toolbar {
|
||||||
|
t := &Toolbar{
|
||||||
|
browsingPane: browsingPane,
|
||||||
|
navBtnsContainer: container.NewHBox(),
|
||||||
|
navBtnsPageMap: make(map[controller.PageName]fyne.Resource),
|
||||||
|
settingsMenu: fyne.NewMenu(""),
|
||||||
|
}
|
||||||
|
t.ExtendBaseWidget(t)
|
||||||
|
|
||||||
|
browsingPane.OnHistoryChanged = t.updateNavButtons
|
||||||
|
|
||||||
|
t.home = ttwidget.NewButtonWithIcon("", theme.HomeIcon(), homeFunc)
|
||||||
|
t.home.SetToolTip(lang.L("Home"))
|
||||||
|
t.back = ttwidget.NewButtonWithIcon("", theme.NavigateBackIcon(), browsingPane.GoBack)
|
||||||
|
t.back.SetToolTip(lang.L("Back"))
|
||||||
|
t.forward = ttwidget.NewButtonWithIcon("", theme.NavigateNextIcon(), browsingPane.GoForward)
|
||||||
|
t.forward.SetToolTip(lang.L("Forward"))
|
||||||
|
t.reload = ttwidget.NewButtonWithIcon("", theme.ViewRefreshIcon(), browsingPane.Reload)
|
||||||
|
t.reload.SetToolTip(lang.L("Reload"))
|
||||||
|
|
||||||
|
t.setupNavigationButtons(navigateFn)
|
||||||
|
|
||||||
|
t.quickSearchBtn = ttwidget.NewButtonWithIcon("", theme.SearchIcon(), showSearchFn)
|
||||||
|
t.quickSearchBtn.SetToolTip(lang.L("Search Everywhere"))
|
||||||
|
t.settingsBtn = ttwidget.NewButtonWithIcon("", theme.SettingsIcon(), func() {
|
||||||
|
p := widget.NewPopUpMenu(t.settingsMenu,
|
||||||
|
fyne.CurrentApp().Driver().CanvasForObject(t.settingsBtn))
|
||||||
|
p.ShowAtPosition(fyne.NewPos(t.Size().Width-p.MinSize().Width+4,
|
||||||
|
t.navBtnsContainer.MinSize().Height+theme.Padding()))
|
||||||
|
})
|
||||||
|
t.settingsBtn.SetToolTip(lang.L("Menu"))
|
||||||
|
|
||||||
|
t.updateNavButtons()
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRadioButtonVisible sets whether the radio button is visible
|
||||||
|
func (t *Toolbar) SetRadioButtonVisible(vis bool) {
|
||||||
|
if vis {
|
||||||
|
t.radioBtn.Show()
|
||||||
|
} else {
|
||||||
|
t.radioBtn.Hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSettingsMenuItem adds an item to the Settings menu
|
||||||
|
func (t *Toolbar) AddSettingsMenuItem(label string, icon fyne.Resource, action func()) {
|
||||||
|
item := fyne.NewMenuItem(label, action)
|
||||||
|
item.Icon = icon
|
||||||
|
t.settingsMenu.Items = append(t.settingsMenu.Items, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSettingsSubmenu adds a submenu to the Settings menu
|
||||||
|
func (t *Toolbar) AddSettingsSubmenu(label string, icon fyne.Resource, menu *fyne.Menu) {
|
||||||
|
item := fyne.NewMenuItem(label, nil)
|
||||||
|
item.ChildMenu = menu
|
||||||
|
item.Icon = icon
|
||||||
|
t.settingsMenu.Items = append(t.settingsMenu.Items, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSettingsMenuSeparator adds a separator to the settings menu
|
||||||
|
func (t *Toolbar) AddSettingsMenuSeparator() {
|
||||||
|
t.settingsMenu.Items = append(t.settingsMenu.Items,
|
||||||
|
fyne.NewMenuItemSeparator())
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSubmenuForMenuItem sets (changes) the submenu for the first menu item matching the label
|
||||||
|
func (t *Toolbar) SetSubmenuForMenuItem(label string, submenu *fyne.Menu) {
|
||||||
|
for _, item := range t.settingsMenu.Items {
|
||||||
|
if item.Label == label {
|
||||||
|
item.ChildMenu = submenu
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisableNavigationButtons disables all navigation buttons
|
||||||
|
func (t *Toolbar) DisableNavigationButtons() {
|
||||||
|
for _, obj := range t.navBtnsContainer.Objects {
|
||||||
|
obj.(fyne.Disableable).Disable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnableNavigationButtons enables all navigation buttons
|
||||||
|
func (t *Toolbar) EnableNavigationButtons() {
|
||||||
|
for _, obj := range t.navBtnsContainer.Objects {
|
||||||
|
obj.(fyne.Disableable).Enable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ActivateNavigationButton executes the button action for the nth navigation button
|
||||||
|
func (t *Toolbar) ActivateNavigationButton(n int) {
|
||||||
|
if n < len(t.navBtnsContainer.Objects) {
|
||||||
|
btn := t.navBtnsContainer.Objects[n].(*ttwidget.Button)
|
||||||
|
if !btn.Disabled() && !btn.Hidden {
|
||||||
|
btn.OnTapped()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Toolbar) CreateRenderer() fyne.WidgetRenderer {
|
||||||
|
content := container.New(layouts.NewLeftMiddleRightLayout(0, 0),
|
||||||
|
container.NewHBox(t.home, t.back, t.forward, t.reload),
|
||||||
|
t.navBtnsContainer,
|
||||||
|
container.NewHBox(layout.NewSpacer(), t.quickSearchBtn, t.settingsBtn))
|
||||||
|
return widget.NewSimpleRenderer(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Toolbar) setupNavigationButtons(navigateFn func(controller.Route)) {
|
||||||
|
t.addNavigationButton(myTheme.NowPlayingIcon, controller.NowPlaying, func() {
|
||||||
|
navigateFn(controller.NowPlayingRoute())
|
||||||
|
})
|
||||||
|
t.addNavigationButton(myTheme.FavoriteIcon, controller.Favorites, func() {
|
||||||
|
navigateFn(controller.FavoritesRoute())
|
||||||
|
})
|
||||||
|
t.addNavigationButton(myTheme.AlbumIcon, controller.Albums, func() {
|
||||||
|
navigateFn(controller.AlbumsRoute())
|
||||||
|
})
|
||||||
|
t.addNavigationButton(myTheme.ArtistIcon, controller.Artists, func() {
|
||||||
|
navigateFn(controller.ArtistsRoute())
|
||||||
|
})
|
||||||
|
t.addNavigationButton(myTheme.GenreIcon, controller.Genres, func() {
|
||||||
|
navigateFn(controller.GenresRoute())
|
||||||
|
})
|
||||||
|
t.addNavigationButton(myTheme.PlaylistIcon, controller.Playlists, func() {
|
||||||
|
navigateFn(controller.PlaylistsRoute())
|
||||||
|
})
|
||||||
|
t.addNavigationButton(myTheme.TracksIcon, controller.Tracks, func() {
|
||||||
|
navigateFn(controller.TracksRoute())
|
||||||
|
})
|
||||||
|
t.radioBtn = t.addNavigationButton(myTheme.RadioIcon, controller.Radios, func() {
|
||||||
|
navigateFn(controller.RadiosRoute())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Toolbar) addNavigationButton(icon fyne.Resource, pageName controller.PageName, action func()) *ttwidget.Button {
|
||||||
|
// make a copy of the icon, because it can change the color
|
||||||
|
browsingPaneIcon := theme.NewThemedResource(icon)
|
||||||
|
btn := ttwidget.NewButtonWithIcon("", browsingPaneIcon, action)
|
||||||
|
btn.SetToolTip(lang.L(pageName.String()))
|
||||||
|
t.navBtnsContainer.Add(btn)
|
||||||
|
t.navBtnsPageMap[pageName] = browsingPaneIcon
|
||||||
|
return btn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Toolbar) updateNavButtons() {
|
||||||
|
if t.browsingPane.CanGoBack() {
|
||||||
|
t.back.Enable()
|
||||||
|
} else {
|
||||||
|
t.back.Disable()
|
||||||
|
}
|
||||||
|
if t.browsingPane.CanGoForward() {
|
||||||
|
t.forward.Enable()
|
||||||
|
} else {
|
||||||
|
t.forward.Disable()
|
||||||
|
}
|
||||||
|
|
||||||
|
p := t.browsingPane.CurrentPage()
|
||||||
|
for pageName, icon := range t.navBtnsPageMap {
|
||||||
|
if pageName == p.Page {
|
||||||
|
icon.(*theme.ThemedResource).ColorName = theme.ColorNamePrimary
|
||||||
|
} else {
|
||||||
|
icon.(*theme.ThemedResource).ColorName = theme.ColorNameForeground
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Refresh()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user