Updates #116: add tool tips to buttons and various UI elements
This commit is contained in:
+25
-15
@@ -3,6 +3,7 @@ package browsing
|
||||
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"
|
||||
@@ -11,6 +12,8 @@ import (
|
||||
"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 Page interface {
|
||||
@@ -60,14 +63,14 @@ type BrowsingPane struct {
|
||||
|
||||
curPage Page
|
||||
|
||||
home *widget.Button
|
||||
forward *widget.Button
|
||||
back *widget.Button
|
||||
reload *widget.Button
|
||||
home *ttwidget.Button
|
||||
forward *ttwidget.Button
|
||||
back *ttwidget.Button
|
||||
reload *ttwidget.Button
|
||||
history []SavedPage
|
||||
historyIdx int
|
||||
|
||||
settingsBtn *widget.Button
|
||||
settingsBtn *ttwidget.Button
|
||||
settingsMenu *fyne.Menu
|
||||
navBtnsContainer *fyne.Container
|
||||
pageContainer *fyne.Container
|
||||
@@ -78,22 +81,28 @@ type BrowsingPane struct {
|
||||
func NewBrowsingPane(app *backend.App, contr *controller.Controller, onGoHome func()) *BrowsingPane {
|
||||
b := &BrowsingPane{app: app}
|
||||
b.ExtendBaseWidget(b)
|
||||
b.home = widget.NewButtonWithIcon("", theme.HomeIcon(), onGoHome)
|
||||
b.back = widget.NewButtonWithIcon("", theme.NavigateBackIcon(), b.GoBack)
|
||||
b.forward = widget.NewButtonWithIcon("", theme.NavigateNextIcon(), b.GoForward)
|
||||
b.reload = widget.NewButtonWithIcon("", theme.ViewRefreshIcon(), b.Reload)
|
||||
b.home = ttwidget.NewButtonWithIcon("", theme.HomeIcon(), onGoHome)
|
||||
b.home.SetToolTip(lang.L("Home"))
|
||||
b.back = ttwidget.NewButtonWithIcon("", theme.NavigateBackIcon(), b.GoBack)
|
||||
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("Reload")
|
||||
b.app.PlaybackManager.OnSongChange(b.onSongChange)
|
||||
b.app.PlaybackManager.OnPlayTimeUpdate(b.onPlayTimeUpdate)
|
||||
b.app.PlaybackManager.OnQueueChange(b.onQueueChange)
|
||||
bkgrnd := myTheme.NewThemedRectangle(myTheme.ColorNamePageBackground)
|
||||
b.pageContainer = container.NewStack(bkgrnd, layout.NewSpacer())
|
||||
b.settingsBtn = widget.NewButtonWithIcon("", theme.SettingsIcon(), func() {
|
||||
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()))
|
||||
})
|
||||
quickSearchBtn := widget.NewButtonWithIcon("", theme.SearchIcon(), contr.ShowQuickSearch)
|
||||
b.settingsBtn.SetToolTip("Menu")
|
||||
quickSearchBtn := ttwidget.NewButtonWithIcon("", theme.SearchIcon(), contr.ShowQuickSearch)
|
||||
quickSearchBtn.SetToolTip("Search Everywhere")
|
||||
b.settingsMenu = fyne.NewMenu("")
|
||||
b.navBtnsContainer = container.NewHBox()
|
||||
b.navBtnsPageMap = map[controller.PageName]fyne.Resource{}
|
||||
@@ -146,10 +155,11 @@ func (b *BrowsingPane) AddSettingsMenuSeparator() {
|
||||
fyne.NewMenuItemSeparator())
|
||||
}
|
||||
|
||||
func (b *BrowsingPane) AddNavigationButton(icon fyne.Resource, pageName controller.PageName, action func()) *widget.Button {
|
||||
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 := widget.NewButtonWithIcon("", browsingPaneIcon, action)
|
||||
btn := ttwidget.NewButtonWithIcon("", browsingPaneIcon, action)
|
||||
btn.SetToolTip(lang.L(pageName.String()))
|
||||
b.navBtnsContainer.Add(btn)
|
||||
b.navBtnsPageMap[pageName] = browsingPaneIcon
|
||||
return btn
|
||||
@@ -157,13 +167,13 @@ func (b *BrowsingPane) AddNavigationButton(icon fyne.Resource, pageName controll
|
||||
|
||||
func (b *BrowsingPane) DisableNavigationButtons() {
|
||||
for _, obj := range b.navBtnsContainer.Objects {
|
||||
obj.(*widget.Button).Disable()
|
||||
obj.(fyne.Disableable).Disable()
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BrowsingPane) EnableNavigationButtons() {
|
||||
for _, obj := range b.navBtnsContainer.Objects {
|
||||
obj.(*widget.Button).Enable()
|
||||
obj.(fyne.Disableable).Enable()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
fynetooltip "github.com/dweymouth/fyne-tooltip"
|
||||
"github.com/dweymouth/supersonic/backend"
|
||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||
"github.com/dweymouth/supersonic/backend/player"
|
||||
@@ -528,8 +529,10 @@ func (c *Controller) ShowSettingsDialog(themeUpdateCallbk func(), themeFiles map
|
||||
}
|
||||
dlg.OnPageNeedsRefresh = c.RefreshPageFunc
|
||||
pop := widget.NewModalPopUp(dlg, c.MainWindow.Canvas())
|
||||
fynetooltip.AddPopUpToolTipLayer(pop)
|
||||
dlg.OnDismiss = func() {
|
||||
pop.Hide()
|
||||
fynetooltip.DestroyPopUpToolTipLayer(pop)
|
||||
c.doModalClosed()
|
||||
c.App.SaveConfigFile()
|
||||
}
|
||||
|
||||
@@ -18,6 +18,37 @@ const (
|
||||
Radios
|
||||
)
|
||||
|
||||
func (p PageName) String() string {
|
||||
switch p {
|
||||
case Album:
|
||||
return "Album"
|
||||
case Albums:
|
||||
return "Albums"
|
||||
case Artist:
|
||||
return "Artist"
|
||||
case Artists:
|
||||
return "Artists"
|
||||
case Genre:
|
||||
return "Genre"
|
||||
case Genres:
|
||||
return "Genres"
|
||||
case Favorites:
|
||||
return "Favorites"
|
||||
case NowPlaying:
|
||||
return "Now Playing"
|
||||
case Playlist:
|
||||
return "Playlist"
|
||||
case Playlists:
|
||||
return "Playlists"
|
||||
case Tracks:
|
||||
return "All Tracks"
|
||||
case Radios:
|
||||
return "Internet Radio Stations"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
type Route struct {
|
||||
Page PageName
|
||||
Arg string
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package dialogs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/layout"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
ttwidget "github.com/dweymouth/fyne-tooltip/widget"
|
||||
"github.com/dweymouth/supersonic/ui/layouts"
|
||||
myTheme "github.com/dweymouth/supersonic/ui/theme"
|
||||
"github.com/dweymouth/supersonic/ui/util"
|
||||
@@ -17,7 +20,8 @@ type GraphicEqualizer struct {
|
||||
OnChanged func(band int, gain float64)
|
||||
OnPreampChanged func(gain float64)
|
||||
|
||||
container *fyne.Container
|
||||
bandSliders []*eqSlider
|
||||
container *fyne.Container
|
||||
}
|
||||
|
||||
func NewGraphicEqualizer(preamp float64, bandFreqs []string, bandGains []float64) *GraphicEqualizer {
|
||||
@@ -36,7 +40,8 @@ func (g *GraphicEqualizer) buildSliders(preamp float64, bands []string, bandGain
|
||||
layout.NewSpacer(),
|
||||
newCaptionTextSizeLabel("-12", fyne.TextAlignTrailing),
|
||||
)
|
||||
bandSliders := container.New(layouts.NewGridLayoutWithColumnsAndPadding(len(bands)+2, -16))
|
||||
g.bandSliders = make([]*eqSlider, len(bands))
|
||||
bandSlidersCtr := container.New(layouts.NewGridLayoutWithColumnsAndPadding(len(bands)+2, -16))
|
||||
pre := newCaptionTextSizeLabel("Pre", fyne.TextAlignCenter)
|
||||
preampSlider := newEQSlider()
|
||||
preampSlider.SetValue(preamp)
|
||||
@@ -44,24 +49,28 @@ func (g *GraphicEqualizer) buildSliders(preamp float64, bands []string, bandGain
|
||||
if g.OnPreampChanged != nil {
|
||||
g.OnPreampChanged(f)
|
||||
}
|
||||
preampSlider.UpdateToolTip()
|
||||
}
|
||||
bandSliders.Add(container.NewBorder(nil, pre, nil, nil, preampSlider))
|
||||
bandSliders.Add(container.NewBorder(nil, widget.NewLabel(""), nil, nil, rng))
|
||||
preampSlider.UpdateToolTip()
|
||||
bandSlidersCtr.Add(container.NewBorder(nil, pre, nil, nil, preampSlider))
|
||||
bandSlidersCtr.Add(container.NewBorder(nil, widget.NewLabel(""), nil, nil, rng))
|
||||
for i, band := range bands {
|
||||
s := newEQSlider()
|
||||
if i < len(bandGains) {
|
||||
s.SetValue(bandGains[i])
|
||||
s.UpdateToolTip()
|
||||
}
|
||||
s.OnChanged = func(i int) func(float64) {
|
||||
return func(f float64) {
|
||||
if g.OnChanged != nil {
|
||||
g.OnChanged(i, f)
|
||||
}
|
||||
_i := i
|
||||
s.OnChanged = func(f float64) {
|
||||
if g.OnChanged != nil {
|
||||
g.OnChanged(_i, f)
|
||||
}
|
||||
}(i)
|
||||
g.bandSliders[_i].UpdateToolTip()
|
||||
}
|
||||
l := newCaptionTextSizeLabel(band, fyne.TextAlignCenter)
|
||||
c := container.NewBorder(nil, l, nil, nil, s)
|
||||
bandSliders.Add(c)
|
||||
bandSlidersCtr.Add(c)
|
||||
g.bandSliders[i] = s
|
||||
}
|
||||
g.container = container.NewStack(
|
||||
container.NewBorder(nil, widget.NewLabel(""), nil, nil,
|
||||
@@ -73,7 +82,7 @@ func (g *GraphicEqualizer) buildSliders(preamp float64, bands []string, bandGain
|
||||
),
|
||||
),
|
||||
),
|
||||
bandSliders,
|
||||
bandSlidersCtr,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -90,23 +99,29 @@ func (g *GraphicEqualizer) CreateRenderer() fyne.WidgetRenderer {
|
||||
}
|
||||
|
||||
type eqSlider struct {
|
||||
widget.Slider
|
||||
tappedAt int64
|
||||
ttwidget.Slider
|
||||
}
|
||||
|
||||
func newEQSlider() *eqSlider {
|
||||
s := &eqSlider{
|
||||
Slider: widget.Slider{
|
||||
Orientation: widget.Vertical,
|
||||
Min: -12,
|
||||
Max: 12,
|
||||
Step: 0.1,
|
||||
Slider: ttwidget.Slider{
|
||||
Slider: widget.Slider{
|
||||
Orientation: widget.Vertical,
|
||||
Min: -12,
|
||||
Max: 12,
|
||||
Step: 0.1,
|
||||
},
|
||||
},
|
||||
}
|
||||
s.UpdateToolTip()
|
||||
s.ExtendBaseWidget(s)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *eqSlider) UpdateToolTip() {
|
||||
s.SetToolTip(fmt.Sprintf("%0.1f dB", s.Value))
|
||||
}
|
||||
|
||||
// We implement our own double tapping so that the Tapped behavior
|
||||
// can be triggered instantly.
|
||||
func (s *eqSlider) DoubleTapped(e *fyne.PointEvent) {
|
||||
|
||||
+9
-4
@@ -7,6 +7,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
fynetooltip "github.com/dweymouth/fyne-tooltip"
|
||||
"github.com/dweymouth/supersonic/backend"
|
||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||
"github.com/dweymouth/supersonic/res"
|
||||
@@ -40,7 +41,7 @@ type MainWindow struct {
|
||||
container *fyne.Container
|
||||
|
||||
// needs to bes shown/hidden when switching between servers based on whether they support radio
|
||||
radioBtn *widget.Button
|
||||
radioBtn fyne.CanvasObject
|
||||
}
|
||||
|
||||
func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string, app *backend.App) MainWindow {
|
||||
@@ -49,6 +50,7 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string,
|
||||
Window: fyneApp.NewWindow(displayAppName),
|
||||
theme: theme.NewMyTheme(&app.Config.Theme, app.ThemesDir()),
|
||||
}
|
||||
fynetooltip.SetToolTipTextSizeName(theme.SizeNameSubText)
|
||||
|
||||
m.theme.NormalFont = app.Config.Application.FontNormalTTF
|
||||
m.theme.BoldFont = app.Config.Application.FontBoldTTF
|
||||
@@ -80,7 +82,7 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string,
|
||||
|
||||
m.BottomPanel = NewBottomPanel(app.PlaybackManager, app.ImageManager, m.Controller)
|
||||
m.container = container.NewBorder(nil, m.BottomPanel, nil, nil, m.BrowsingPane)
|
||||
m.Window.SetContent(m.container)
|
||||
m.Window.SetContent(fynetooltip.AddWindowToolTipLayer(m.container, m.Window.Canvas()))
|
||||
m.setInitialSize()
|
||||
app.PlaybackManager.OnSongChange(func(item mediaprovider.MediaItem, _ *mediaprovider.Track) {
|
||||
if item == nil {
|
||||
@@ -191,8 +193,11 @@ func (m *MainWindow) RunOnServerConnectedTasks(app *backend.App, displayAppName
|
||||
}
|
||||
|
||||
_, supportsRadio := m.App.ServerManager.Server.(mediaprovider.RadioProvider)
|
||||
m.radioBtn.Hidden = !supportsRadio
|
||||
m.radioBtn.Refresh()
|
||||
if supportsRadio {
|
||||
m.radioBtn.Show()
|
||||
} else {
|
||||
m.radioBtn.Hide()
|
||||
}
|
||||
|
||||
m.App.SaveConfigFile()
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"fyne.io/fyne/v2/layout"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
ttwidget "github.com/dweymouth/fyne-tooltip/widget"
|
||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||
"github.com/dweymouth/supersonic/sharedutil"
|
||||
myTheme "github.com/dweymouth/supersonic/ui/theme"
|
||||
@@ -22,7 +23,7 @@ import (
|
||||
)
|
||||
|
||||
type AlbumFilterButton struct {
|
||||
widget.Button
|
||||
ttwidget.Button
|
||||
|
||||
OnChanged func()
|
||||
GenreDisabled bool
|
||||
@@ -37,10 +38,13 @@ type AlbumFilterButton struct {
|
||||
func NewAlbumFilterButton(filter mediaprovider.AlbumFilter, fetchGenresFunc func() ([]*mediaprovider.Genre, error)) *AlbumFilterButton {
|
||||
a := &AlbumFilterButton{
|
||||
filter: filter,
|
||||
Button: widget.Button{
|
||||
Icon: theme.NewThemedResource(myTheme.FilterIcon),
|
||||
Button: ttwidget.Button{
|
||||
Button: widget.Button{
|
||||
Icon: theme.NewThemedResource(myTheme.FilterIcon),
|
||||
},
|
||||
},
|
||||
}
|
||||
a.SetToolTip(lang.L("Filter albums"))
|
||||
a.OnTapped = a.showFilterDialog
|
||||
a.ExtendBaseWidget(a)
|
||||
a.genreListChan = make(chan []string)
|
||||
|
||||
@@ -3,6 +3,7 @@ package widgets
|
||||
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"
|
||||
@@ -31,7 +32,9 @@ func NewAuxControls(initialVolume int) *AuxControls {
|
||||
showQueue: NewIconButton(myTheme.PlayQueueIcon, nil),
|
||||
}
|
||||
a.loop.IconSize = IconButtonSizeSmaller
|
||||
a.loop.SetToolTip(lang.L("Shuffle"))
|
||||
a.showQueue.IconSize = IconButtonSizeSmaller
|
||||
a.showQueue.SetToolTip(lang.L("Show play queue"))
|
||||
a.container = container.NewHBox(
|
||||
layout.NewSpacer(),
|
||||
container.NewVBox(
|
||||
@@ -125,6 +128,7 @@ func NewVolumeControl(initialVol int) *VolumeControl {
|
||||
v := &VolumeControl{}
|
||||
v.ExtendBaseWidget(v)
|
||||
v.icon = NewIconButton(theme.VolumeUpIcon(), v.toggleMute)
|
||||
v.icon.SetToolTip("Mute")
|
||||
v.icon.IconSize = IconButtonSizeSmaller
|
||||
v.slider = NewVolumeSlider(100)
|
||||
v.lastVol = initialVol
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fyne.io/fyne/v2/driver/desktop"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
ttwidget "github.com/dweymouth/fyne-tooltip/widget"
|
||||
|
||||
myTheme "github.com/dweymouth/supersonic/ui/theme"
|
||||
)
|
||||
@@ -20,7 +21,7 @@ const (
|
||||
)
|
||||
|
||||
type IconButton struct {
|
||||
widget.BaseWidget
|
||||
ttwidget.ToolTipWidget
|
||||
|
||||
Highlighted bool
|
||||
IconSize IconButtonSize
|
||||
@@ -84,7 +85,8 @@ func (i *IconButton) TypedKey(e *fyne.KeyEvent) {
|
||||
func (i *IconButton) TypedRune(r rune) {
|
||||
}
|
||||
|
||||
func (i *IconButton) MouseIn(*desktop.MouseEvent) {
|
||||
func (i *IconButton) MouseIn(e *desktop.MouseEvent) {
|
||||
i.ToolTipWidget.MouseIn(e)
|
||||
if !i.hovered {
|
||||
defer i.Refresh()
|
||||
}
|
||||
@@ -92,13 +94,15 @@ func (i *IconButton) MouseIn(*desktop.MouseEvent) {
|
||||
}
|
||||
|
||||
func (i *IconButton) MouseOut() {
|
||||
i.ToolTipWidget.MouseOut()
|
||||
if i.hovered {
|
||||
defer i.Refresh()
|
||||
}
|
||||
i.hovered = false
|
||||
}
|
||||
|
||||
func (i *IconButton) MouseMoved(*desktop.MouseEvent) {
|
||||
func (i *IconButton) MouseMoved(e *desktop.MouseEvent) {
|
||||
i.ToolTipWidget.MouseMoved(e)
|
||||
}
|
||||
|
||||
func (i *IconButton) MinSize() fyne.Size {
|
||||
|
||||
@@ -5,6 +5,7 @@ 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"
|
||||
@@ -128,8 +129,11 @@ func NewPlayerControls() *PlayerControls {
|
||||
}
|
||||
|
||||
pc.prev = NewIconButton(theme.MediaSkipPreviousIcon(), func() {})
|
||||
pc.prev.SetToolTip(lang.L("Previous"))
|
||||
pc.next = NewIconButton(theme.MediaSkipNextIcon(), func() {})
|
||||
pc.next.SetToolTip(lang.L("Next"))
|
||||
pc.playpause = NewIconButton(theme.MediaPlayIcon(), func() {})
|
||||
pc.playpause.SetToolTip(lang.L("Play"))
|
||||
pc.playpause.IconSize = IconButtonSizeBigger
|
||||
|
||||
buttons := container.NewHBox(layout.NewSpacer(), pc.prev, pc.playpause, pc.next, layout.NewSpacer())
|
||||
@@ -165,8 +169,10 @@ func (pc *PlayerControls) OnPlayPause(f func()) {
|
||||
func (pc *PlayerControls) SetPlaying(playing bool) {
|
||||
if playing {
|
||||
pc.playpause.SetIcon(theme.MediaPauseIcon())
|
||||
pc.playpause.SetToolTip(lang.L("Pause"))
|
||||
} else {
|
||||
pc.playpause.SetIcon(theme.MediaPlayIcon())
|
||||
pc.playpause.SetToolTip(lang.L("Play"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user