Merge pull request #85 from dweymouth/develop
Misc. cleanup and refactoring
This commit is contained in:
@@ -186,8 +186,8 @@ func NewAlbumPageHeader(page *AlbumPage) *AlbumPageHeader {
|
|||||||
container.NewVBox(
|
container.NewVBox(
|
||||||
container.New(&layouts.VboxCustomPadding{ExtraPad: -12}, a.artistLabel, a.genreLabel, a.miscLabel),
|
container.New(&layouts.VboxCustomPadding{ExtraPad: -12}, a.artistLabel, a.genreLabel, a.miscLabel),
|
||||||
container.NewVBox(
|
container.NewVBox(
|
||||||
container.NewHBox(widgets.NewHSpace(2), playButton, shuffleBtn),
|
container.NewHBox(util.NewHSpace(2), playButton, shuffleBtn),
|
||||||
container.NewHBox(widgets.NewHSpace(2), a.toggleFavButton),
|
container.NewHBox(util.NewHSpace(2), a.toggleFavButton),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"supersonic/backend"
|
"supersonic/backend"
|
||||||
"supersonic/sharedutil"
|
"supersonic/sharedutil"
|
||||||
"supersonic/ui/controller"
|
"supersonic/ui/controller"
|
||||||
|
"supersonic/ui/util"
|
||||||
"supersonic/ui/widgets"
|
"supersonic/ui/widgets"
|
||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
@@ -92,7 +93,7 @@ func (a *AlbumsPage) createContainer(searchgrid bool) {
|
|||||||
g = a.searchGrid
|
g = a.searchGrid
|
||||||
}
|
}
|
||||||
a.container = container.NewBorder(
|
a.container = container.NewBorder(
|
||||||
container.NewHBox(widgets.NewHSpace(6), a.titleDisp, sortVbox, layout.NewSpacer(), searchVbox, widgets.NewHSpace(12)),
|
container.NewHBox(util.NewHSpace(6), a.titleDisp, sortVbox, layout.NewSpacer(), searchVbox, util.NewHSpace(12)),
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ func newArtistPage(artistID string, cfg *backend.ArtistPageConfig, pm *backend.P
|
|||||||
viewToggle.OnChanged = a.onViewChange
|
viewToggle.OnChanged = a.onViewChange
|
||||||
//line := canvas.NewLine(theme.TextColor())
|
//line := canvas.NewLine(theme.TextColor())
|
||||||
viewToggleRow := container.NewBorder(nil, nil,
|
viewToggleRow := container.NewBorder(nil, nil,
|
||||||
container.NewHBox(&widgets.HSpace{Width: 5}, viewToggle), nil,
|
container.NewHBox(util.NewHSpace(5), viewToggle), nil,
|
||||||
layout.NewSpacer(),
|
layout.NewSpacer(),
|
||||||
)
|
)
|
||||||
a.container = container.NewBorder(
|
a.container = container.NewBorder(
|
||||||
@@ -329,7 +329,7 @@ func (a *ArtistPageHeader) createContainer() {
|
|||||||
container.NewVBox(
|
container.NewVBox(
|
||||||
container.New(&layouts.VboxCustomPadding{ExtraPad: -10},
|
container.New(&layouts.VboxCustomPadding{ExtraPad: -10},
|
||||||
a.titleDisp, a.biographyDisp, a.similarArtists),
|
a.titleDisp, a.biographyDisp, a.similarArtists),
|
||||||
container.NewHBox(widgets.NewHSpace(2), a.favoriteBtn, a.playBtn, a.playRadioBtn)))
|
container.NewHBox(util.NewHSpace(2), a.favoriteBtn, a.playBtn, a.playRadioBtn)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArtistPageHeader) CreateRenderer() fyne.WidgetRenderer {
|
func (a *ArtistPageHeader) CreateRenderer() fyne.WidgetRenderer {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ type ArtistsGenresPage struct {
|
|||||||
sm *backend.ServerManager
|
sm *backend.ServerManager
|
||||||
titleDisp *widget.RichText
|
titleDisp *widget.RichText
|
||||||
container *fyne.Container
|
container *fyne.Container
|
||||||
list *widgets.ArtistGenrePlaylist
|
list *widgets.ArtistGenreList
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewArtistsGenresPage(isGenresPage bool, contr *controller.Controller, sm *backend.ServerManager) *ArtistsGenresPage {
|
func NewArtistsGenresPage(isGenresPage bool, contr *controller.Controller, sm *backend.ServerManager) *ArtistsGenresPage {
|
||||||
@@ -41,7 +41,7 @@ func NewArtistsGenresPage(isGenresPage bool, contr *controller.Controller, sm *b
|
|||||||
}
|
}
|
||||||
a.ExtendBaseWidget(a)
|
a.ExtendBaseWidget(a)
|
||||||
a.titleDisp.Segments[0].(*widget.TextSegment).Style.SizeName = theme.SizeNameHeadingText
|
a.titleDisp.Segments[0].(*widget.TextSegment).Style.SizeName = theme.SizeNameHeadingText
|
||||||
a.list = widgets.NewArtistGenrePlaylist(nil)
|
a.list = widgets.NewArtistGenreList(nil)
|
||||||
a.list.ShowAlbumCount = true
|
a.list.ShowAlbumCount = true
|
||||||
a.list.ShowTrackCount = isGenresPage
|
a.list.ShowTrackCount = isGenresPage
|
||||||
a.list.OnNavTo = func(id string) {
|
a.list.OnNavTo = func(id string) {
|
||||||
@@ -103,11 +103,11 @@ func (s *savedArtistsGenresPage) Restore() Page {
|
|||||||
return NewArtistsGenresPage(s.isGenresPage, s.contr, s.sm)
|
return NewArtistsGenresPage(s.isGenresPage, s.contr, s.sm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArtistsGenresPage) buildArtistListModel(artists *subsonic.ArtistsID3) []widgets.ArtistGenrePlaylistItemModel {
|
func (a *ArtistsGenresPage) buildArtistListModel(artists *subsonic.ArtistsID3) []widgets.ArtistGenreListItemModel {
|
||||||
model := make([]widgets.ArtistGenrePlaylistItemModel, 0)
|
model := make([]widgets.ArtistGenreListItemModel, 0)
|
||||||
for _, idx := range artists.Index {
|
for _, idx := range artists.Index {
|
||||||
for _, artist := range idx.Artist {
|
for _, artist := range idx.Artist {
|
||||||
model = append(model, widgets.ArtistGenrePlaylistItemModel{
|
model = append(model, widgets.ArtistGenreListItemModel{
|
||||||
ID: artist.ID,
|
ID: artist.ID,
|
||||||
Name: artist.Name,
|
Name: artist.Name,
|
||||||
AlbumCount: artist.AlbumCount,
|
AlbumCount: artist.AlbumCount,
|
||||||
@@ -118,10 +118,10 @@ func (a *ArtistsGenresPage) buildArtistListModel(artists *subsonic.ArtistsID3) [
|
|||||||
return model
|
return model
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArtistsGenresPage) buildGenresListModel(genres []*subsonic.Genre) []widgets.ArtistGenrePlaylistItemModel {
|
func (a *ArtistsGenresPage) buildGenresListModel(genres []*subsonic.Genre) []widgets.ArtistGenreListItemModel {
|
||||||
model := make([]widgets.ArtistGenrePlaylistItemModel, 0)
|
model := make([]widgets.ArtistGenreListItemModel, 0)
|
||||||
for _, genre := range genres {
|
for _, genre := range genres {
|
||||||
model = append(model, widgets.ArtistGenrePlaylistItemModel{
|
model = append(model, widgets.ArtistGenreListItemModel{
|
||||||
ID: genre.Name,
|
ID: genre.Name,
|
||||||
Name: genre.Name,
|
Name: genre.Name,
|
||||||
AlbumCount: genre.AlbumCount,
|
AlbumCount: genre.AlbumCount,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"supersonic/res"
|
"supersonic/res"
|
||||||
"supersonic/ui/controller"
|
"supersonic/ui/controller"
|
||||||
"supersonic/ui/layouts"
|
"supersonic/ui/layouts"
|
||||||
|
"supersonic/ui/util"
|
||||||
"supersonic/ui/widgets"
|
"supersonic/ui/widgets"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -89,7 +90,7 @@ func (a *FavoritesPage) connectGridActions() {
|
|||||||
func (a *FavoritesPage) createContainer(initialView fyne.CanvasObject) {
|
func (a *FavoritesPage) createContainer(initialView fyne.CanvasObject) {
|
||||||
searchVbox := container.NewVBox(layout.NewSpacer(), a.searcher.Entry, layout.NewSpacer())
|
searchVbox := container.NewVBox(layout.NewSpacer(), a.searcher.Entry, layout.NewSpacer())
|
||||||
a.container = container.NewBorder(
|
a.container = container.NewBorder(
|
||||||
container.NewHBox(widgets.NewHSpace(9), a.titleDisp, container.NewCenter(a.toggleBtns), layout.NewSpacer(), searchVbox, widgets.NewHSpace(15)),
|
container.NewHBox(util.NewHSpace(9), a.titleDisp, container.NewCenter(a.toggleBtns), layout.NewSpacer(), searchVbox, util.NewHSpace(15)),
|
||||||
nil, nil, nil, initialView)
|
nil, nil, nil, initialView)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +155,7 @@ func (a *FavoritesPage) Reload() {
|
|||||||
}
|
}
|
||||||
if a.artistListCtr != nil {
|
if a.artistListCtr != nil {
|
||||||
// refresh favorite artists view
|
// refresh favorite artists view
|
||||||
al := a.artistListCtr.Objects[0].(*widgets.ArtistGenrePlaylist)
|
al := a.artistListCtr.Objects[0].(*widgets.ArtistGenreList)
|
||||||
al.Items = buildArtistListModel(starred.Artist)
|
al.Items = buildArtistListModel(starred.Artist)
|
||||||
if a.toggleBtns.ActivatedButtonIndex() == 1 {
|
if a.toggleBtns.ActivatedButtonIndex() == 1 {
|
||||||
// favorite artists view is visible
|
// favorite artists view is visible
|
||||||
@@ -263,7 +264,7 @@ func (a *FavoritesPage) onShowFavoriteArtists() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
model := buildArtistListModel(s.Artist)
|
model := buildArtistListModel(s.Artist)
|
||||||
artistList := widgets.NewArtistGenrePlaylist(model)
|
artistList := widgets.NewArtistGenreList(model)
|
||||||
artistList.ShowAlbumCount = true
|
artistList.ShowAlbumCount = true
|
||||||
artistList.OnNavTo = func(artistID string) {
|
artistList.OnNavTo = func(artistID string) {
|
||||||
a.contr.NavigateTo(controller.ArtistRoute(artistID))
|
a.contr.NavigateTo(controller.ArtistRoute(artistID))
|
||||||
@@ -281,10 +282,10 @@ func (a *FavoritesPage) onShowFavoriteArtists() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildArtistListModel(artists []*subsonic.ArtistID3) []widgets.ArtistGenrePlaylistItemModel {
|
func buildArtistListModel(artists []*subsonic.ArtistID3) []widgets.ArtistGenreListItemModel {
|
||||||
model := make([]widgets.ArtistGenrePlaylistItemModel, 0)
|
model := make([]widgets.ArtistGenreListItemModel, 0)
|
||||||
for _, ar := range artists {
|
for _, ar := range artists {
|
||||||
model = append(model, widgets.ArtistGenrePlaylistItemModel{
|
model = append(model, widgets.ArtistGenreListItemModel{
|
||||||
ID: ar.ID,
|
ID: ar.ID,
|
||||||
Name: ar.Name,
|
Name: ar.Name,
|
||||||
AlbumCount: ar.AlbumCount,
|
AlbumCount: ar.AlbumCount,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"supersonic/backend"
|
"supersonic/backend"
|
||||||
"supersonic/res"
|
"supersonic/res"
|
||||||
"supersonic/ui/controller"
|
"supersonic/ui/controller"
|
||||||
|
"supersonic/ui/util"
|
||||||
"supersonic/ui/widgets"
|
"supersonic/ui/widgets"
|
||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
@@ -70,7 +71,7 @@ func (g *GenrePage) createContainer(searchGrid bool) {
|
|||||||
}
|
}
|
||||||
playRandomVbox := container.NewVBox(layout.NewSpacer(), g.playRandom, layout.NewSpacer())
|
playRandomVbox := container.NewVBox(layout.NewSpacer(), g.playRandom, layout.NewSpacer())
|
||||||
g.container = container.NewBorder(
|
g.container = container.NewBorder(
|
||||||
container.NewHBox(widgets.NewHSpace(6), g.titleDisp, playRandomVbox, layout.NewSpacer(), searchVbox, widgets.NewHSpace(15)),
|
container.NewHBox(util.NewHSpace(6), g.titleDisp, playRandomVbox, layout.NewSpacer(), searchVbox, util.NewHSpace(15)),
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/layout"
|
||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
"golang.org/x/net/html"
|
"golang.org/x/net/html"
|
||||||
)
|
)
|
||||||
@@ -53,3 +55,23 @@ func RichTextSegsFromHTMLString(s string) []widget.RichTextSegment {
|
|||||||
|
|
||||||
return segs
|
return segs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HSpace struct {
|
||||||
|
widget.BaseWidget
|
||||||
|
|
||||||
|
Width float32
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHSpace(w float32) *HSpace {
|
||||||
|
h := &HSpace{Width: w}
|
||||||
|
h.ExtendBaseWidget(h)
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HSpace) MinSize() fyne.Size {
|
||||||
|
return fyne.NewSize(h.Width, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HSpace) CreateRenderer() fyne.WidgetRenderer {
|
||||||
|
return widget.NewSimpleRenderer(layout.NewSpacer())
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ArtistGenrePlaylistItemModel struct {
|
type ArtistGenreListItemModel struct {
|
||||||
ID string
|
ID string
|
||||||
Name string
|
Name string
|
||||||
AlbumCount int
|
AlbumCount int
|
||||||
@@ -17,10 +17,10 @@ type ArtistGenrePlaylistItemModel struct {
|
|||||||
Favorite bool
|
Favorite bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type ArtistGenrePlaylist struct {
|
type ArtistGenreList struct {
|
||||||
widget.BaseWidget
|
widget.BaseWidget
|
||||||
|
|
||||||
Items []ArtistGenrePlaylistItemModel
|
Items []ArtistGenreListItemModel
|
||||||
ShowAlbumCount bool
|
ShowAlbumCount bool
|
||||||
ShowTrackCount bool
|
ShowTrackCount bool
|
||||||
OnNavTo func(string)
|
OnNavTo func(string)
|
||||||
@@ -31,10 +31,10 @@ type ArtistGenrePlaylist struct {
|
|||||||
container *fyne.Container
|
container *fyne.Container
|
||||||
}
|
}
|
||||||
|
|
||||||
type ArtistGenrePlaylistRow struct {
|
type ArtistGenreListRow struct {
|
||||||
widget.BaseWidget
|
widget.BaseWidget
|
||||||
|
|
||||||
Item ArtistGenrePlaylistItemModel
|
Item ArtistGenreListItemModel
|
||||||
OnTapped func()
|
OnTapped func()
|
||||||
|
|
||||||
nameLabel *widget.Label
|
nameLabel *widget.Label
|
||||||
@@ -44,8 +44,8 @@ type ArtistGenrePlaylistRow struct {
|
|||||||
container *fyne.Container
|
container *fyne.Container
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewArtistGenrePlaylistRow(layout *layouts.ColumnsLayout) *ArtistGenrePlaylistRow {
|
func NewArtistGenreListRow(layout *layouts.ColumnsLayout) *ArtistGenreListRow {
|
||||||
a := &ArtistGenrePlaylistRow{
|
a := &ArtistGenreListRow{
|
||||||
nameLabel: widget.NewLabel(""),
|
nameLabel: widget.NewLabel(""),
|
||||||
albumCountLabel: widget.NewLabel(""),
|
albumCountLabel: widget.NewLabel(""),
|
||||||
trackCountLabel: widget.NewLabel(""),
|
trackCountLabel: widget.NewLabel(""),
|
||||||
@@ -57,8 +57,8 @@ func NewArtistGenrePlaylistRow(layout *layouts.ColumnsLayout) *ArtistGenrePlayli
|
|||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewArtistGenrePlaylist(items []ArtistGenrePlaylistItemModel) *ArtistGenrePlaylist {
|
func NewArtistGenreList(items []ArtistGenreListItemModel) *ArtistGenreList {
|
||||||
a := &ArtistGenrePlaylist{
|
a := &ArtistGenreList{
|
||||||
Items: items,
|
Items: items,
|
||||||
columnsLayout: layouts.NewColumnsLayout([]float32{-1, 125, 125}),
|
columnsLayout: layouts.NewColumnsLayout([]float32{-1, 125, 125}),
|
||||||
}
|
}
|
||||||
@@ -68,12 +68,12 @@ func NewArtistGenrePlaylist(items []ArtistGenrePlaylistItemModel) *ArtistGenrePl
|
|||||||
a.list = widget.NewList(
|
a.list = widget.NewList(
|
||||||
func() int { return len(a.Items) },
|
func() int { return len(a.Items) },
|
||||||
func() fyne.CanvasObject {
|
func() fyne.CanvasObject {
|
||||||
r := NewArtistGenrePlaylistRow(a.columnsLayout)
|
r := NewArtistGenreListRow(a.columnsLayout)
|
||||||
r.OnTapped = func() { a.onRowDoubleTapped(r.Item) }
|
r.OnTapped = func() { a.onRowDoubleTapped(r.Item) }
|
||||||
return r
|
return r
|
||||||
},
|
},
|
||||||
func(id widget.ListItemID, item fyne.CanvasObject) {
|
func(id widget.ListItemID, item fyne.CanvasObject) {
|
||||||
row := item.(*ArtistGenrePlaylistRow)
|
row := item.(*ArtistGenreListRow)
|
||||||
row.Item = a.Items[id]
|
row.Item = a.Items[id]
|
||||||
row.albumCountLabel.Hidden = !a.ShowAlbumCount
|
row.albumCountLabel.Hidden = !a.ShowAlbumCount
|
||||||
row.trackCountLabel.Hidden = !a.ShowTrackCount
|
row.trackCountLabel.Hidden = !a.ShowTrackCount
|
||||||
@@ -87,28 +87,28 @@ func NewArtistGenrePlaylist(items []ArtistGenrePlaylistItemModel) *ArtistGenrePl
|
|||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArtistGenrePlaylist) Refresh() {
|
func (a *ArtistGenreList) Refresh() {
|
||||||
a.hdr.SetColumnVisible(1, a.ShowAlbumCount)
|
a.hdr.SetColumnVisible(1, a.ShowAlbumCount)
|
||||||
a.hdr.SetColumnVisible(2, a.ShowTrackCount)
|
a.hdr.SetColumnVisible(2, a.ShowTrackCount)
|
||||||
a.BaseWidget.Refresh()
|
a.BaseWidget.Refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArtistGenrePlaylist) onRowDoubleTapped(item ArtistGenrePlaylistItemModel) {
|
func (a *ArtistGenreList) onRowDoubleTapped(item ArtistGenreListItemModel) {
|
||||||
if a.OnNavTo != nil {
|
if a.OnNavTo != nil {
|
||||||
a.OnNavTo(item.ID)
|
a.OnNavTo(item.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArtistGenrePlaylistRow) Tapped(*fyne.PointEvent) {
|
func (a *ArtistGenreListRow) Tapped(*fyne.PointEvent) {
|
||||||
if a.OnTapped != nil {
|
if a.OnTapped != nil {
|
||||||
a.OnTapped()
|
a.OnTapped()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArtistGenrePlaylist) CreateRenderer() fyne.WidgetRenderer {
|
func (a *ArtistGenreList) CreateRenderer() fyne.WidgetRenderer {
|
||||||
return widget.NewSimpleRenderer(a.container)
|
return widget.NewSimpleRenderer(a.container)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArtistGenrePlaylistRow) CreateRenderer() fyne.WidgetRenderer {
|
func (a *ArtistGenreListRow) CreateRenderer() fyne.WidgetRenderer {
|
||||||
return widget.NewSimpleRenderer(a.container)
|
return widget.NewSimpleRenderer(a.container)
|
||||||
}
|
}
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package widgets
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fyne.io/fyne/v2"
|
|
||||||
"fyne.io/fyne/v2/layout"
|
|
||||||
"fyne.io/fyne/v2/widget"
|
|
||||||
)
|
|
||||||
|
|
||||||
type HSpace struct {
|
|
||||||
widget.BaseWidget
|
|
||||||
|
|
||||||
Width float32
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewHSpace(w float32) *HSpace {
|
|
||||||
h := &HSpace{Width: w}
|
|
||||||
h.ExtendBaseWidget(h)
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *HSpace) MinSize() fyne.Size {
|
|
||||||
return fyne.NewSize(h.Width, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *HSpace) CreateRenderer() fyne.WidgetRenderer {
|
|
||||||
return widget.NewSimpleRenderer(layout.NewSpacer())
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
package widgets
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fyne.io/fyne/v2"
|
|
||||||
"fyne.io/fyne/v2/theme"
|
|
||||||
"fyne.io/fyne/v2/widget"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SearchEntry struct {
|
|
||||||
widget.Entry
|
|
||||||
height float32
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSearchEntry() *SearchEntry {
|
|
||||||
sf := &SearchEntry{}
|
|
||||||
sf.ExtendBaseWidget(sf)
|
|
||||||
// this is a bit hacky
|
|
||||||
sf.height = widget.NewEntry().MinSize().Height
|
|
||||||
sf.PlaceHolder = "Search"
|
|
||||||
c := NewClearTextButton()
|
|
||||||
c.OnTapped = func() {
|
|
||||||
sf.SetText("")
|
|
||||||
}
|
|
||||||
sf.ActionItem = c
|
|
||||||
return sf
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SearchEntry) Refresh() {
|
|
||||||
if s.Text == "" {
|
|
||||||
s.ActionItem.(*clearTextButton).Resource = theme.SearchIcon()
|
|
||||||
} else {
|
|
||||||
s.ActionItem.(*clearTextButton).Resource = theme.ContentClearIcon()
|
|
||||||
}
|
|
||||||
s.Entry.Refresh()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SearchEntry) MinSize() fyne.Size {
|
|
||||||
return fyne.NewSize(200, s.height)
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ fyne.Tappable = (*clearTextButton)(nil)
|
|
||||||
|
|
||||||
type clearTextButton struct {
|
|
||||||
widget.Icon
|
|
||||||
|
|
||||||
OnTapped func()
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClearTextButton() *clearTextButton {
|
|
||||||
c := &clearTextButton{}
|
|
||||||
c.ExtendBaseWidget(c)
|
|
||||||
c.Resource = theme.SearchIcon()
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *clearTextButton) Tapped(*fyne.PointEvent) {
|
|
||||||
if c.OnTapped != nil {
|
|
||||||
c.OnTapped()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,8 +3,15 @@ package widgets
|
|||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/theme"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Searcher is a search entry widget that will issue a search command
|
||||||
|
// (aka call OnSearched) when a short span of time has elapsed since
|
||||||
|
// the user typed into the widget.
|
||||||
type Searcher struct {
|
type Searcher struct {
|
||||||
Entry *SearchEntry
|
Entry *SearchEntry
|
||||||
OnSearched func(string)
|
OnSearched func(string)
|
||||||
@@ -61,3 +68,56 @@ func (s *Searcher) sendSearch(text string) {
|
|||||||
s.OnSearched(text)
|
s.OnSearched(text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SearchEntry struct {
|
||||||
|
widget.Entry
|
||||||
|
height float32
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSearchEntry() *SearchEntry {
|
||||||
|
sf := &SearchEntry{}
|
||||||
|
sf.ExtendBaseWidget(sf)
|
||||||
|
// this is a bit hacky
|
||||||
|
sf.height = widget.NewEntry().MinSize().Height
|
||||||
|
sf.PlaceHolder = "Search"
|
||||||
|
c := NewClearTextButton()
|
||||||
|
c.OnTapped = func() {
|
||||||
|
sf.SetText("")
|
||||||
|
}
|
||||||
|
sf.ActionItem = c
|
||||||
|
return sf
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SearchEntry) Refresh() {
|
||||||
|
if s.Text == "" {
|
||||||
|
s.ActionItem.(*clearTextButton).Resource = theme.SearchIcon()
|
||||||
|
} else {
|
||||||
|
s.ActionItem.(*clearTextButton).Resource = theme.ContentClearIcon()
|
||||||
|
}
|
||||||
|
s.Entry.Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SearchEntry) MinSize() fyne.Size {
|
||||||
|
return fyne.NewSize(200, s.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ fyne.Tappable = (*clearTextButton)(nil)
|
||||||
|
|
||||||
|
type clearTextButton struct {
|
||||||
|
widget.Icon
|
||||||
|
|
||||||
|
OnTapped func()
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewClearTextButton() *clearTextButton {
|
||||||
|
c := &clearTextButton{}
|
||||||
|
c.ExtendBaseWidget(c)
|
||||||
|
c.Resource = theme.SearchIcon()
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *clearTextButton) Tapped(*fyne.PointEvent) {
|
||||||
|
if c.OnTapped != nil {
|
||||||
|
c.OnTapped()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
package widgets
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fyne.io/fyne/v2"
|
|
||||||
"fyne.io/fyne/v2/driver/desktop"
|
|
||||||
"fyne.io/fyne/v2/widget"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TappableIcon struct {
|
|
||||||
widget.Icon
|
|
||||||
|
|
||||||
OnTapped func()
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewTappbaleIcon(res fyne.Resource) *TappableIcon {
|
|
||||||
icon := &TappableIcon{}
|
|
||||||
icon.ExtendBaseWidget(icon)
|
|
||||||
icon.SetResource(res)
|
|
||||||
|
|
||||||
return icon
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *TappableIcon) Tapped(_ *fyne.PointEvent) {
|
|
||||||
if t.OnTapped != nil {
|
|
||||||
t.OnTapped()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *TappableIcon) TappedSecondary(_ *fyne.PointEvent) {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *TappableIcon) Cursor() desktop.Cursor {
|
|
||||||
return desktop.PointerCursor
|
|
||||||
}
|
|
||||||
@@ -7,6 +7,35 @@ import (
|
|||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TappableIcon is a tappable wrapper of widget.Icon
|
||||||
|
type TappableIcon struct {
|
||||||
|
widget.Icon
|
||||||
|
|
||||||
|
OnTapped func()
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTappbaleIcon(res fyne.Resource) *TappableIcon {
|
||||||
|
icon := &TappableIcon{}
|
||||||
|
icon.ExtendBaseWidget(icon)
|
||||||
|
icon.SetResource(res)
|
||||||
|
|
||||||
|
return icon
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TappableIcon) Tapped(_ *fyne.PointEvent) {
|
||||||
|
if t.OnTapped != nil {
|
||||||
|
t.OnTapped()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TappableIcon) TappedSecondary(_ *fyne.PointEvent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TappableIcon) Cursor() desktop.Cursor {
|
||||||
|
return desktop.PointerCursor
|
||||||
|
}
|
||||||
|
|
||||||
|
// TappableImage is a tappable wrapper of canvas.Image
|
||||||
type TappableImage struct {
|
type TappableImage struct {
|
||||||
widget.BaseWidget
|
widget.BaseWidget
|
||||||
canvas.Image
|
canvas.Image
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package widgets
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fyne.io/fyne/v2"
|
|
||||||
"fyne.io/fyne/v2/canvas"
|
|
||||||
"fyne.io/fyne/v2/theme"
|
|
||||||
"fyne.io/fyne/v2/widget"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ThickSeparator struct {
|
|
||||||
widget.BaseWidget
|
|
||||||
line canvas.Line
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewThickSeparator() *ThickSeparator {
|
|
||||||
t := &ThickSeparator{
|
|
||||||
line: canvas.Line{
|
|
||||||
StrokeWidth: 3,
|
|
||||||
StrokeColor: theme.DisabledColor(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
t.ExtendBaseWidget(t)
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *ThickSeparator) CreateRenderer() fyne.WidgetRenderer {
|
|
||||||
return widget.NewSimpleRenderer(&t.line)
|
|
||||||
}
|
|
||||||
+12
-3
@@ -32,10 +32,19 @@ const (
|
|||||||
type Tracklist struct {
|
type Tracklist struct {
|
||||||
widget.BaseWidget
|
widget.BaseWidget
|
||||||
|
|
||||||
Tracks []*subsonic.Child
|
// Tracks is the set of tracks displayed by the widget.
|
||||||
|
Tracks []*subsonic.Child
|
||||||
|
|
||||||
|
// AutoNumber sets whether to auto-number the tracks 1..N in display order,
|
||||||
|
// or to use the number from the track's metadata
|
||||||
AutoNumber bool
|
AutoNumber bool
|
||||||
|
|
||||||
|
// AuxiliaryMenuItems sets additional menu items appended to the context menu
|
||||||
// must be set before the context menu is shown for the first time
|
// must be set before the context menu is shown for the first time
|
||||||
AuxiliaryMenuItems []*fyne.MenuItem
|
AuxiliaryMenuItems []*fyne.MenuItem
|
||||||
|
|
||||||
|
// DisablePlaybackMenu sets whether to disable playback options in
|
||||||
|
// the tracklist context menu.
|
||||||
DisablePlaybackMenu bool
|
DisablePlaybackMenu bool
|
||||||
|
|
||||||
// user action callbacks
|
// user action callbacks
|
||||||
@@ -75,7 +84,7 @@ func NewTracklist(tracks []*subsonic.Child) *Tracklist {
|
|||||||
t.OnColumnVisibilityMenuShown(pop)
|
t.OnColumnVisibilityMenuShown(pop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
playingIcon := container.NewCenter(container.NewHBox(NewHSpace(2), widget.NewIcon(theme.MediaPlayIcon())))
|
playingIcon := container.NewCenter(container.NewHBox(util.NewHSpace(2), widget.NewIcon(theme.MediaPlayIcon())))
|
||||||
t.list = widget.NewList(
|
t.list = widget.NewList(
|
||||||
func() int { return len(t.Tracks) },
|
func() int { return len(t.Tracks) },
|
||||||
func() fyne.CanvasObject {
|
func() fyne.CanvasObject {
|
||||||
|
|||||||
Reference in New Issue
Block a user