Add tool tips to tracklist names, etc + refactoring
This commit is contained in:
+38
-27
@@ -50,7 +50,8 @@ type Controller struct {
|
||||
RefreshPageFunc func()
|
||||
|
||||
popUpQueueMutex sync.Mutex
|
||||
popUpQueue *widgets.PlayQueueList
|
||||
popUpQueue *widget.PopUp
|
||||
popUpQueueList *widgets.PlayQueueList
|
||||
popUpQueueLastUsed int64
|
||||
escapablePopUp *widget.PopUp
|
||||
haveModal bool
|
||||
@@ -65,18 +66,22 @@ func New(app *backend.App, appVersion string, mainWindow fyne.Window) *Controlle
|
||||
}
|
||||
c.initVisualizations()
|
||||
c.App.PlaybackManager.OnQueueChange(func() {
|
||||
c.popUpQueueMutex.Lock()
|
||||
defer c.popUpQueueMutex.Unlock()
|
||||
if c.popUpQueue != nil {
|
||||
c.popUpQueue.SetItems(c.App.PlaybackManager.GetPlayQueue())
|
||||
c.popUpQueueList.SetItems(c.App.PlaybackManager.GetPlayQueue())
|
||||
}
|
||||
})
|
||||
c.App.PlaybackManager.OnSongChange(func(track mediaprovider.MediaItem, _ *mediaprovider.Track) {
|
||||
c.popUpQueueMutex.Lock()
|
||||
defer c.popUpQueueMutex.Unlock()
|
||||
if c.popUpQueue == nil {
|
||||
return
|
||||
}
|
||||
if track == nil {
|
||||
c.popUpQueue.SetNowPlaying("")
|
||||
c.popUpQueueList.SetNowPlaying("")
|
||||
} else {
|
||||
c.popUpQueue.SetNowPlaying(track.Metadata().ID)
|
||||
c.popUpQueueList.SetNowPlaying(track.Metadata().ID)
|
||||
}
|
||||
})
|
||||
return c
|
||||
@@ -116,10 +121,28 @@ func (m *Controller) HaveModal() bool {
|
||||
func (m *Controller) ShowPopUpPlayQueue() {
|
||||
m.popUpQueueMutex.Lock()
|
||||
if m.popUpQueue == nil {
|
||||
m.popUpQueue = widgets.NewPlayQueueList(m.App.ImageManager, false)
|
||||
m.popUpQueue.Reorderable = true
|
||||
m.popUpQueue.SetItems(m.App.PlaybackManager.GetPlayQueue())
|
||||
m.ConnectPlayQueuelistActions(m.popUpQueue)
|
||||
m.popUpQueueList = widgets.NewPlayQueueList(m.App.ImageManager, false)
|
||||
m.popUpQueueList.Reorderable = true
|
||||
m.popUpQueueList.SetItems(m.App.PlaybackManager.GetPlayQueue())
|
||||
m.ConnectPlayQueuelistActions(m.popUpQueueList)
|
||||
|
||||
title := widget.NewRichTextWithText(lang.L("Play Queue"))
|
||||
title.Segments[0].(*widget.TextSegment).Style.Alignment = fyne.TextAlignCenter
|
||||
title.Segments[0].(*widget.TextSegment).Style.TextStyle.Bold = true
|
||||
ctr := container.NewBorder(title, nil, nil, nil,
|
||||
container.NewPadded(m.popUpQueueList),
|
||||
)
|
||||
m.popUpQueue = widget.NewPopUp(ctr, m.MainWindow.Canvas())
|
||||
fynetooltip.AddPopUpToolTipLayer(m.popUpQueue)
|
||||
|
||||
container.NewThemeOverride(m.popUpQueue, myTheme.WithColorTransformOverride(
|
||||
theme.ColorNameOverlayBackground,
|
||||
func(c color.Color) color.Color {
|
||||
c_ := c.(color.NRGBA)
|
||||
c_.A = 245
|
||||
return c_
|
||||
},
|
||||
))
|
||||
|
||||
// free popUpQueue if it hasn't been used in awhile
|
||||
go func() {
|
||||
@@ -128,7 +151,9 @@ func (m *Controller) ShowPopUpPlayQueue() {
|
||||
m.popUpQueueMutex.Lock()
|
||||
now := time.Now().UnixMilli()
|
||||
if m.popUpQueueLastUsed < now-120_000 /*2 min*/ {
|
||||
fynetooltip.DestroyPopUpToolTipLayer(m.popUpQueue)
|
||||
m.popUpQueue = nil
|
||||
m.popUpQueueList = nil
|
||||
m.popUpQueueLastUsed = 0
|
||||
m.popUpQueueMutex.Unlock()
|
||||
t.Stop()
|
||||
@@ -139,31 +164,17 @@ func (m *Controller) ShowPopUpPlayQueue() {
|
||||
}()
|
||||
}
|
||||
m.popUpQueueLastUsed = time.Now().UnixMilli()
|
||||
popUpQueue := m.popUpQueue
|
||||
popUpQueueList := m.popUpQueueList
|
||||
pop := m.popUpQueue
|
||||
m.popUpQueueMutex.Unlock()
|
||||
|
||||
npID := ""
|
||||
if np := m.App.PlaybackManager.NowPlaying(); np != nil {
|
||||
npID = np.Metadata().ID
|
||||
}
|
||||
popUpQueue.SetNowPlaying(npID)
|
||||
popUpQueue.UnselectAll()
|
||||
popUpQueueList.SetNowPlaying(npID)
|
||||
popUpQueueList.UnselectAll()
|
||||
|
||||
title := widget.NewRichTextWithText(lang.L("Play Queue"))
|
||||
title.Segments[0].(*widget.TextSegment).Style.Alignment = fyne.TextAlignCenter
|
||||
title.Segments[0].(*widget.TextSegment).Style.TextStyle.Bold = true
|
||||
ctr := container.NewBorder(title, nil, nil, nil,
|
||||
container.NewPadded(m.popUpQueue),
|
||||
)
|
||||
pop := widget.NewPopUp(ctr, m.MainWindow.Canvas())
|
||||
container.NewThemeOverride(pop, myTheme.WithColorTransformOverride(
|
||||
theme.ColorNameOverlayBackground,
|
||||
func(c color.Color) color.Color {
|
||||
c_ := c.(color.NRGBA)
|
||||
c_.A = 245
|
||||
return c_
|
||||
},
|
||||
))
|
||||
m.ClosePopUpOnEscape(pop)
|
||||
minSize := fyne.NewSize(300, 400)
|
||||
maxSize := fyne.NewSize(800, 1000)
|
||||
@@ -172,7 +183,7 @@ func (m *Controller) ShowPopUpPlayQueue() {
|
||||
fyne.NewSize(canvasSize.Width*0.4, canvasSize.Height*0.5),
|
||||
))
|
||||
pop.Resize(size)
|
||||
popUpQueue.ScrollToNowPlaying() // must come after resize
|
||||
popUpQueueList.ScrollToNowPlaying() // must come after resize
|
||||
pop.ShowAtPosition(fyne.NewPos(
|
||||
canvasSize.Width-size.Width-10,
|
||||
canvasSize.Height-size.Height-100,
|
||||
|
||||
@@ -12,10 +12,12 @@ import (
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/driver/desktop"
|
||||
"fyne.io/fyne/v2/lang"
|
||||
"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/res"
|
||||
"github.com/dweymouth/supersonic/sharedutil"
|
||||
@@ -252,6 +254,18 @@ func NewTruncatingLabel() *widget.Label {
|
||||
return rt
|
||||
}
|
||||
|
||||
func NewTruncatingTooltipRichText() *ttwidget.RichText {
|
||||
rt := ttwidget.NewRichTextWithText("")
|
||||
rt.Truncation = fyne.TextTruncateEllipsis
|
||||
return rt
|
||||
}
|
||||
|
||||
func NewTruncatingTooltipLabel() *ttwidget.Label {
|
||||
rt := ttwidget.NewLabel("")
|
||||
rt.Truncation = fyne.TextTruncateEllipsis
|
||||
return rt
|
||||
}
|
||||
|
||||
func NewTrailingAlignLabel() *widget.Label {
|
||||
rt := widget.NewLabel("")
|
||||
rt.Alignment = fyne.TextAlignTrailing
|
||||
@@ -269,6 +283,14 @@ func LocalizeSlice(s []string) []string {
|
||||
return sharedutil.MapSlice(s, func(s string) string { return lang.L(s) })
|
||||
}
|
||||
|
||||
type ToolTipRichText struct {
|
||||
ttwidget.RichText
|
||||
|
||||
OnMouseIn func(e *desktop.MouseEvent)
|
||||
OnMouseOut func()
|
||||
OnTapped func(e *fyne.PointEvent)
|
||||
}
|
||||
|
||||
type HSpace struct {
|
||||
widget.BaseWidget
|
||||
|
||||
|
||||
+51
-19
@@ -1,12 +1,14 @@
|
||||
package widgets
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/driver/desktop"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
|
||||
@@ -72,6 +74,7 @@ func (g *FocusList) FocusNeighbor(curItem widget.ListItemID, up bool) {
|
||||
var _ fyne.Tappable = (*FocusListRowBase)(nil)
|
||||
var _ fyne.Widget = (*FocusListRowBase)(nil)
|
||||
var _ fyne.Focusable = (*FocusListRowBase)(nil)
|
||||
var _ desktop.Hoverable = (*FocusListRowBase)(nil)
|
||||
|
||||
// Base type used for all list rows in widgets such as Tracklist, etc.
|
||||
type FocusListRowBase struct {
|
||||
@@ -81,14 +84,16 @@ type FocusListRowBase struct {
|
||||
Content fyne.CanvasObject
|
||||
Selected bool
|
||||
Focused bool
|
||||
hovered bool
|
||||
|
||||
OnTapped func()
|
||||
OnDoubleTapped func()
|
||||
OnFocusNeighbor func(up bool) //TODO: func(up, selecting bool)
|
||||
|
||||
tappedAt int64 // unixMillis
|
||||
focusedRect *canvas.Rectangle
|
||||
selectionRect *canvas.Rectangle
|
||||
focusedRect canvas.Rectangle
|
||||
selectionRect canvas.Rectangle
|
||||
hoverRect canvas.Rectangle
|
||||
}
|
||||
|
||||
func (l *FocusListRowBase) SetOnTapped(f func()) {
|
||||
@@ -139,12 +144,14 @@ func (l *FocusListRowBase) Tapped(*fyne.PointEvent) {
|
||||
|
||||
func (l *FocusListRowBase) FocusGained() {
|
||||
l.Focused = true
|
||||
l.Refresh()
|
||||
l.focusedRect.FillColor = theme.HoverColor()
|
||||
l.focusedRect.Refresh()
|
||||
}
|
||||
|
||||
func (l *FocusListRowBase) FocusLost() {
|
||||
l.Focused = false
|
||||
l.Refresh()
|
||||
l.focusedRect.FillColor = color.Transparent
|
||||
l.focusedRect.Refresh()
|
||||
}
|
||||
|
||||
func (l *FocusListRowBase) TypedKey(e *fyne.KeyEvent) {
|
||||
@@ -180,26 +187,51 @@ func (l *FocusListRowBase) TypedKey(e *fyne.KeyEvent) {
|
||||
func (l *FocusListRowBase) TypedRune(r rune) {
|
||||
}
|
||||
|
||||
func (l *FocusListRowBase) MouseIn(e *desktop.MouseEvent) {
|
||||
l.hovered = true
|
||||
l.hoverRect.FillColor = theme.HoverColor()
|
||||
l.hoverRect.Refresh()
|
||||
}
|
||||
|
||||
func (l *FocusListRowBase) MouseMoved(e *desktop.MouseEvent) {
|
||||
}
|
||||
|
||||
func (l *FocusListRowBase) MouseOut() {
|
||||
l.hovered = false
|
||||
l.hoverRect.FillColor = color.Transparent
|
||||
l.hoverRect.Refresh()
|
||||
}
|
||||
|
||||
func (l *FocusListRowBase) Refresh() {
|
||||
l.focusedRect.FillColor = theme.HoverColor()
|
||||
l.focusedRect.Hidden = !l.Focused
|
||||
l.selectionRect.FillColor = theme.SelectionColor()
|
||||
l.selectionRect.Hidden = !l.Selected
|
||||
l.updateBackgroundRendering()
|
||||
l.BaseWidget.Refresh()
|
||||
}
|
||||
|
||||
func (l *FocusListRowBase) updateBackgroundRendering() {
|
||||
if l.Selected {
|
||||
l.selectionRect.FillColor = theme.SelectionColor()
|
||||
} else {
|
||||
l.selectionRect.FillColor = color.Transparent
|
||||
}
|
||||
if l.Focused {
|
||||
l.focusedRect.FillColor = theme.HoverColor()
|
||||
} else {
|
||||
l.focusedRect.FillColor = color.Transparent
|
||||
}
|
||||
if l.hovered {
|
||||
l.hoverRect.FillColor = theme.HoverColor()
|
||||
} else {
|
||||
l.hoverRect.FillColor = color.Transparent
|
||||
}
|
||||
}
|
||||
|
||||
func (l *FocusListRowBase) CreateRenderer() fyne.WidgetRenderer {
|
||||
if l.selectionRect == nil {
|
||||
l.selectionRect = canvas.NewRectangle(theme.SelectionColor())
|
||||
l.selectionRect.CornerRadius = theme.SelectionRadiusSize()
|
||||
l.selectionRect.Hidden = !l.Selected
|
||||
}
|
||||
if l.focusedRect == nil {
|
||||
l.focusedRect = canvas.NewRectangle(theme.HoverColor())
|
||||
l.focusedRect.CornerRadius = theme.SelectionRadiusSize()
|
||||
l.focusedRect.Hidden = !l.Focused
|
||||
}
|
||||
l.selectionRect.CornerRadius = theme.SelectionRadiusSize()
|
||||
l.focusedRect.CornerRadius = theme.SelectionRadiusSize()
|
||||
l.hoverRect.CornerRadius = theme.SelectionRadiusSize()
|
||||
l.updateBackgroundRendering()
|
||||
|
||||
return widget.NewSimpleRenderer(
|
||||
container.NewStack(l.selectionRect, l.focusedRect, l.Content),
|
||||
container.NewStack(&l.selectionRect, &l.focusedRect, &l.hoverRect, l.Content),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
|
||||
ttwidget "github.com/dweymouth/fyne-tooltip/widget"
|
||||
"github.com/dweymouth/supersonic/res"
|
||||
myTheme "github.com/dweymouth/supersonic/ui/theme"
|
||||
"github.com/dweymouth/supersonic/ui/util"
|
||||
@@ -142,7 +143,7 @@ type GridViewItem struct {
|
||||
|
||||
itemID string
|
||||
secondaryIDs []string
|
||||
primaryText *widget.Hyperlink
|
||||
primaryText *ttwidget.Hyperlink
|
||||
secondaryText *MultiHyperlink
|
||||
suffix string
|
||||
container *fyne.Container
|
||||
@@ -165,7 +166,7 @@ type GridViewItem struct {
|
||||
|
||||
func NewGridViewItem(placeholderResource fyne.Resource) *GridViewItem {
|
||||
g := &GridViewItem{
|
||||
primaryText: widget.NewHyperlink("", nil),
|
||||
primaryText: ttwidget.NewHyperlink("", nil),
|
||||
secondaryText: NewMultiHyperlink(),
|
||||
Cover: newCoverImage(placeholderResource),
|
||||
}
|
||||
@@ -220,6 +221,7 @@ func (g *GridViewItem) Update(model GridViewItemModel) {
|
||||
g.itemID = model.ID
|
||||
g.secondaryIDs = model.SecondaryIDs
|
||||
g.primaryText.SetText(model.Name)
|
||||
g.primaryText.SetToolTip(model.Name)
|
||||
g.secondaryText.BuildSegments(model.Secondary, model.SecondaryIDs)
|
||||
if g.ShowSuffix {
|
||||
g.secondaryText.Suffix = model.Suffix
|
||||
|
||||
@@ -3,8 +3,10 @@ package widgets
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/driver/desktop"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
ttwidget "github.com/dweymouth/fyne-tooltip/widget"
|
||||
)
|
||||
|
||||
type MultiHyperlink struct {
|
||||
@@ -16,7 +18,9 @@ type MultiHyperlink struct {
|
||||
// only if there is enough room
|
||||
Suffix string
|
||||
|
||||
OnTapped func(string)
|
||||
OnMouseIn func(*desktop.MouseEvent)
|
||||
OnMouseOut func()
|
||||
OnTapped func(string)
|
||||
|
||||
SizeName fyne.ThemeSizeName
|
||||
SuffixSizeName fyne.ThemeSizeName
|
||||
@@ -30,7 +34,7 @@ type MultiHyperlink struct {
|
||||
//provider *widget.RichText
|
||||
|
||||
objects []fyne.CanvasObject
|
||||
suffixLabel *widget.RichText
|
||||
suffixLabel *ttwidget.RichText
|
||||
content *fyne.Container
|
||||
}
|
||||
|
||||
@@ -136,7 +140,9 @@ func (c *MultiHyperlink) layoutObjects() {
|
||||
c.content.Objects = c.objects[:2*i-1]
|
||||
if i == len(c.Segments) && c.Suffix != "" {
|
||||
if c.suffixLabel == nil {
|
||||
c.suffixLabel = widget.NewRichTextWithText("· " + c.Suffix)
|
||||
c.suffixLabel = ttwidget.NewRichTextWithText("· " + c.Suffix)
|
||||
c.suffixLabel.OnMouseIn = c.callOnMouseIn
|
||||
c.suffixLabel.OnMouseOut = c.callOnMouseOut
|
||||
} else {
|
||||
c.suffixLabel.Segments[0].(*widget.TextSegment).Text = "· " + c.Suffix
|
||||
}
|
||||
@@ -157,14 +163,18 @@ func (c *MultiHyperlink) layoutObjects() {
|
||||
|
||||
func (c *MultiHyperlink) updateOrReplaceLabel(obj fyne.CanvasObject, text string) fyne.CanvasObject {
|
||||
if obj != nil {
|
||||
if label, ok := obj.(*widget.RichText); ok {
|
||||
if label, ok := obj.(*ttwidget.RichText); ok {
|
||||
ts := label.Segments[0].(*widget.TextSegment)
|
||||
ts.Text = text
|
||||
ts.Style.SizeName = c.sizeName()
|
||||
label.SetToolTip(text)
|
||||
return label
|
||||
}
|
||||
}
|
||||
l := widget.NewRichTextWithText(text)
|
||||
l := ttwidget.NewRichTextWithText(text)
|
||||
l.SetToolTip(text)
|
||||
l.OnMouseIn = c.callOnMouseIn
|
||||
l.OnMouseOut = c.callOnMouseOut
|
||||
l.Segments[0].(*widget.TextSegment).Style.SizeName = c.sizeName()
|
||||
l.Truncation = fyne.TextTruncateEllipsis
|
||||
return l
|
||||
@@ -172,20 +182,34 @@ func (c *MultiHyperlink) updateOrReplaceLabel(obj fyne.CanvasObject, text string
|
||||
|
||||
func (c *MultiHyperlink) updateOrReplaceHyperlink(obj fyne.CanvasObject, text, link string) fyne.CanvasObject {
|
||||
if obj != nil {
|
||||
if l, ok := obj.(*widget.Hyperlink); ok {
|
||||
if l, ok := obj.(*ttwidget.Hyperlink); ok {
|
||||
l.Text = text
|
||||
l.SetToolTip(text)
|
||||
l.SizeName = c.sizeName()
|
||||
l.OnTapped = func() { c.onSegmentTapped(link) }
|
||||
return l
|
||||
}
|
||||
}
|
||||
l := widget.NewHyperlink(text, nil)
|
||||
l := ttwidget.NewHyperlink(text, nil)
|
||||
l.SetToolTip(text)
|
||||
l.SizeName = c.sizeName()
|
||||
l.Truncation = fyne.TextTruncateEllipsis
|
||||
l.OnTapped = func() { c.onSegmentTapped(link) }
|
||||
return l
|
||||
}
|
||||
|
||||
func (c *MultiHyperlink) callOnMouseIn(e *desktop.MouseEvent) {
|
||||
if f := c.OnMouseIn; f != nil {
|
||||
f(e)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *MultiHyperlink) callOnMouseOut() {
|
||||
if f := c.OnMouseOut; f != nil {
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *MultiHyperlink) newSeparatorLabel() *widget.RichText {
|
||||
rt := widget.NewRichTextWithText(", ")
|
||||
rt.Segments[0].(*widget.TextSegment).Style.SizeName = c.sizeName()
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
// Shows the current album art, track name, artist name, and album name
|
||||
@@ -26,7 +27,7 @@ type NowPlayingCard struct {
|
||||
|
||||
trackName *OptionHyperlink
|
||||
artistName *MultiHyperlink
|
||||
albumName *widget.Hyperlink
|
||||
albumName *ttwidget.Hyperlink
|
||||
cover *ImagePlaceholder
|
||||
menu *widget.PopUpMenu
|
||||
ratingMenu *fyne.MenuItem
|
||||
@@ -46,7 +47,7 @@ func NewNowPlayingCard() *NowPlayingCard {
|
||||
n := &NowPlayingCard{
|
||||
trackName: NewOptionHyperlink(),
|
||||
artistName: NewMultiHyperlink(),
|
||||
albumName: widget.NewHyperlink("", nil),
|
||||
albumName: ttwidget.NewHyperlink("", nil),
|
||||
}
|
||||
n.ExtendBaseWidget(n)
|
||||
n.cover = NewImagePlaceholder(myTheme.TracksIcon, 85)
|
||||
@@ -135,20 +136,23 @@ func (n *NowPlayingCard) CreateRenderer() fyne.WidgetRenderer {
|
||||
|
||||
func (n *NowPlayingCard) Update(track mediaprovider.MediaItem) {
|
||||
if track == nil {
|
||||
n.trackName.SetText("")
|
||||
n.trackName.SetTextAndToolTip("")
|
||||
n.artistName.BuildSegments([]string{}, []string{})
|
||||
n.albumName.SetText("")
|
||||
n.albumName.SetToolTip("")
|
||||
n.cover.Hidden = true
|
||||
} else {
|
||||
n.cover.Hidden = false
|
||||
n.trackName.SetText(track.Metadata().Name)
|
||||
n.trackName.SetTextAndToolTip(track.Metadata().Name)
|
||||
if tr, ok := track.(*mediaprovider.Track); ok {
|
||||
n.artistName.BuildSegments(tr.ArtistNames, tr.ArtistIDs)
|
||||
n.albumName.SetText(tr.Album)
|
||||
n.albumName.SetToolTip(tr.Album)
|
||||
n.cover.PlaceholderIcon = myTheme.TracksIcon
|
||||
} else {
|
||||
n.artistName.BuildSegments([]string{}, []string{})
|
||||
n.albumName.SetText("")
|
||||
n.albumName.SetToolTip("")
|
||||
n.cover.PlaceholderIcon = myTheme.RadioIcon
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,14 @@ import (
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
ttwidget "github.com/dweymouth/fyne-tooltip/widget"
|
||||
)
|
||||
|
||||
// OptionHyperlink is a widget that displays a "vertical dots"/"more" button
|
||||
// to the right of the text, which can show a menu.
|
||||
type OptionHyperlink struct {
|
||||
widget.BaseWidget
|
||||
h *widget.Hyperlink
|
||||
h *ttwidget.Hyperlink
|
||||
b *IconButton
|
||||
|
||||
OnShowMenu func(btnPos fyne.Position)
|
||||
@@ -21,7 +22,7 @@ type OptionHyperlink struct {
|
||||
|
||||
func NewOptionHyperlink() *OptionHyperlink {
|
||||
o := &OptionHyperlink{
|
||||
h: widget.NewHyperlink("", nil),
|
||||
h: ttwidget.NewHyperlink("", nil),
|
||||
}
|
||||
o.h.Truncation = fyne.TextTruncateEllipsis
|
||||
o.b = NewIconButton(theme.MoreVerticalIcon(), func() {
|
||||
@@ -34,8 +35,9 @@ func NewOptionHyperlink() *OptionHyperlink {
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OptionHyperlink) SetText(text string) {
|
||||
func (o *OptionHyperlink) SetTextAndToolTip(text string) {
|
||||
o.h.SetText(text)
|
||||
o.h.SetToolTip(text)
|
||||
o.updatePreferredWidth()
|
||||
o.BaseWidget.Refresh()
|
||||
}
|
||||
|
||||
+13
-10
@@ -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"
|
||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||
"github.com/dweymouth/supersonic/sharedutil"
|
||||
@@ -436,7 +437,7 @@ type PlayQueueListRow struct {
|
||||
playingIcon fyne.CanvasObject
|
||||
num *widget.Label
|
||||
cover *ImagePlaceholder
|
||||
title *widget.Label
|
||||
title *ttwidget.Label
|
||||
artist *MultiHyperlink
|
||||
time *widget.Label
|
||||
}
|
||||
@@ -447,14 +448,18 @@ func NewPlayQueueListRow(playQueueList *PlayQueueList, im *backend.ImageManager,
|
||||
playQueueList: playQueueList,
|
||||
num: widget.NewLabel(""),
|
||||
cover: NewImagePlaceholder(myTheme.TracksIcon, playQueueListThumbnailSize),
|
||||
title: util.NewTruncatingLabel(),
|
||||
title: util.NewTruncatingTooltipLabel(),
|
||||
artist: NewMultiHyperlink(),
|
||||
time: util.NewTrailingAlignLabel(),
|
||||
}
|
||||
p.ExtendBaseWidget(p)
|
||||
|
||||
p.cover.ScaleMode = canvas.ImageScaleFastest
|
||||
p.title.OnMouseIn = p.MouseIn
|
||||
p.title.OnMouseOut = p.MouseOut
|
||||
p.artist.OnTapped = playQueueList.onArtistTapped
|
||||
p.artist.OnMouseIn = p.MouseIn
|
||||
p.artist.OnMouseOut = p.MouseOut
|
||||
p.OnDoubleTapped = func() {
|
||||
playQueueList.onPlayTrackAt(p.ItemID())
|
||||
}
|
||||
@@ -490,15 +495,12 @@ func (p *PlayQueueListRow) TappedSecondary(e *fyne.PointEvent) {
|
||||
}
|
||||
|
||||
func (p *PlayQueueListRow) Update(tm *util.TrackListModel, rowNum int) {
|
||||
changed := false
|
||||
if tm.Selected != p.Selected {
|
||||
p.Selected = tm.Selected
|
||||
changed = true
|
||||
}
|
||||
|
||||
if num := strconv.Itoa(rowNum); p.num.Text != num {
|
||||
p.num.Text = num
|
||||
changed = true
|
||||
}
|
||||
|
||||
// Update info that can change if this row is bound to
|
||||
@@ -514,9 +516,9 @@ func (p *PlayQueueListRow) Update(tm *util.TrackListModel, rowNum int) {
|
||||
p.EnsureUnfocused()
|
||||
p.trackID = meta.ID
|
||||
p.title.Text = meta.Name
|
||||
p.title.SetToolTip(meta.Name)
|
||||
p.artist.BuildSegments(meta.Artists, meta.ArtistIDs)
|
||||
p.time.Text = util.SecondsToMMSS(float64(meta.Duration))
|
||||
changed = true
|
||||
}
|
||||
|
||||
// Render whether track is playing or not
|
||||
@@ -529,10 +531,11 @@ func (p *PlayQueueListRow) Update(tm *util.TrackListModel, rowNum int) {
|
||||
} else {
|
||||
p.Content.(*fyne.Container).Objects[0] = container.NewCenter(p.num)
|
||||
}
|
||||
changed = true
|
||||
}
|
||||
|
||||
if changed {
|
||||
p.Refresh()
|
||||
}
|
||||
// we always need to refresh in case of light/dark change
|
||||
// even if no info changed in the update, since the
|
||||
// PlayQueueList is used in the pop up queue which may be
|
||||
// hidden and re-shown after a theme variant change
|
||||
p.Refresh()
|
||||
}
|
||||
|
||||
@@ -13,6 +13,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"
|
||||
myTheme "github.com/dweymouth/supersonic/ui/theme"
|
||||
"github.com/dweymouth/supersonic/ui/util"
|
||||
@@ -151,7 +152,7 @@ type tracklistRowBase struct {
|
||||
playCount int
|
||||
|
||||
num *widget.Label
|
||||
name *widget.RichText // for bold support
|
||||
name *ttwidget.RichText
|
||||
artist *MultiHyperlink
|
||||
album *MultiHyperlink // for disabled support, if albumID is ""
|
||||
composer *MultiHyperlink
|
||||
@@ -161,9 +162,9 @@ type tracklistRowBase struct {
|
||||
rating *StarRating
|
||||
bitrate *widget.Label
|
||||
plays *widget.Label
|
||||
comment *widget.Label
|
||||
comment *ttwidget.Label
|
||||
size *widget.Label
|
||||
path *widget.Label
|
||||
path *ttwidget.Label
|
||||
|
||||
// must be injected by extending widget
|
||||
setColVisibility func(int, bool) bool
|
||||
@@ -274,13 +275,21 @@ func NewCompactTracklistRow(tracklist *Tracklist, playingIcon fyne.CanvasObject)
|
||||
func (t *tracklistRowBase) create(tracklist *Tracklist) {
|
||||
t.tracklist = tracklist
|
||||
t.num = util.NewTrailingAlignLabel()
|
||||
t.name = util.NewTruncatingRichText()
|
||||
t.name = util.NewTruncatingTooltipRichText()
|
||||
t.name.OnMouseIn = t.MouseIn
|
||||
t.name.OnMouseOut = t.MouseOut
|
||||
t.artist = NewMultiHyperlink()
|
||||
t.artist.OnTapped = tracklist.onArtistTapped
|
||||
t.artist.OnMouseIn = t.MouseIn
|
||||
t.artist.OnMouseOut = t.MouseOut
|
||||
t.album = NewMultiHyperlink()
|
||||
t.album.OnTapped = func(id string) { tracklist.onAlbumTapped(id) }
|
||||
t.album.OnMouseIn = t.MouseIn
|
||||
t.album.OnMouseOut = t.MouseOut
|
||||
t.composer = NewMultiHyperlink()
|
||||
t.composer.OnTapped = func(id string) { tracklist.onArtistTapped(id) }
|
||||
t.composer.OnMouseIn = t.MouseIn
|
||||
t.composer.OnMouseOut = t.MouseOut
|
||||
t.dur = util.NewTrailingAlignLabel()
|
||||
t.year = util.NewTrailingAlignLabel()
|
||||
favorite := NewFavoriteIcon()
|
||||
@@ -291,10 +300,14 @@ func (t *tracklistRowBase) create(tracklist *Tracklist) {
|
||||
t.rating.StarSize = 16
|
||||
t.rating.OnRatingChanged = t.setTrackRating
|
||||
t.plays = util.NewTrailingAlignLabel()
|
||||
t.comment = util.NewTruncatingLabel()
|
||||
t.comment = util.NewTruncatingTooltipLabel()
|
||||
t.comment.OnMouseIn = t.MouseIn
|
||||
t.comment.OnMouseOut = t.MouseOut
|
||||
t.bitrate = util.NewTrailingAlignLabel()
|
||||
t.size = util.NewTrailingAlignLabel()
|
||||
t.path = util.NewTruncatingLabel()
|
||||
t.path = util.NewTruncatingTooltipLabel()
|
||||
t.path.OnMouseIn = t.MouseIn
|
||||
t.path.OnMouseOut = t.MouseOut
|
||||
}
|
||||
|
||||
func (t *tracklistRowBase) SetOnTappedSecondary(f func(*fyne.PointEvent, int)) {
|
||||
@@ -319,6 +332,7 @@ func (t *tracklistRowBase) Update(tm *util.TrackListModel, rowNum int) {
|
||||
t.trackID = id
|
||||
|
||||
t.name.Segments[0].(*widget.TextSegment).Text = tr.Title
|
||||
t.name.SetToolTip(tr.Title)
|
||||
t.artist.BuildSegments(tr.ArtistNames, tr.ArtistIDs)
|
||||
t.album.BuildSegments([]string{tr.Album}, []string{tr.AlbumID})
|
||||
t.composer.BuildSegments(tr.ComposerNames, tr.ComposerIDs)
|
||||
@@ -326,9 +340,11 @@ func (t *tracklistRowBase) Update(tm *util.TrackListModel, rowNum int) {
|
||||
t.year.Text = strconv.Itoa(tr.Year)
|
||||
t.plays.Text = strconv.Itoa(int(tr.PlayCount))
|
||||
t.comment.Text = tr.Comment
|
||||
t.comment.SetToolTip(tr.Comment)
|
||||
t.bitrate.Text = strconv.Itoa(tr.BitRate)
|
||||
t.size.Text = util.BytesToSizeString(tr.Size)
|
||||
t.path.Text = tr.FilePath
|
||||
t.path.SetToolTip(tr.FilePath)
|
||||
changed = true
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user