add albumfilterdialog
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"github.com/dweymouth/supersonic/backend"
|
||||
"github.com/dweymouth/supersonic/sharedutil"
|
||||
"github.com/dweymouth/supersonic/ui/controller"
|
||||
"github.com/dweymouth/supersonic/ui/dialogs"
|
||||
"github.com/dweymouth/supersonic/ui/util"
|
||||
"github.com/dweymouth/supersonic/ui/widgets"
|
||||
|
||||
@@ -27,7 +28,9 @@ type AlbumsPage struct {
|
||||
grid *widgets.GridView
|
||||
searchGrid *widgets.GridView
|
||||
searcher *widgets.SearchEntry
|
||||
filterBtn *widgets.AlbumFilterButton
|
||||
searchText string
|
||||
filter backend.AlbumFilter
|
||||
titleDisp *widget.RichText
|
||||
sortOrder *selectWidget
|
||||
container *fyne.Container
|
||||
@@ -71,11 +74,12 @@ func NewAlbumsPage(cfg *backend.AlbumsPageConfig, contr *controller.Controller,
|
||||
cfg.SortOrder = string(backend.AlbumSortRecentlyAdded)
|
||||
}
|
||||
a.sortOrder.Selected = cfg.SortOrder
|
||||
iter := lm.AlbumsIter(backend.AlbumSortOrder(a.sortOrder.Selected), backend.AlbumFilter{})
|
||||
iter := lm.AlbumsIter(backend.AlbumSortOrder(a.sortOrder.Selected), a.filter)
|
||||
a.grid = widgets.NewGridView(widgets.NewGridViewAlbumIterator(iter), im)
|
||||
contr.ConnectAlbumGridActions(a.grid)
|
||||
a.searcher = widgets.NewSearchEntry()
|
||||
a.searcher.OnSearched = a.OnSearched
|
||||
a.filterBtn = widgets.NewAlbumFilterButton(&a.filter, func(filter *backend.AlbumFilter) fyne.CanvasObject { return dialogs.NewAlbumFilterDialog(filter) })
|
||||
a.createContainer(false)
|
||||
|
||||
return a
|
||||
@@ -89,7 +93,7 @@ func (a *AlbumsPage) createContainer(searchgrid bool) {
|
||||
g = a.searchGrid
|
||||
}
|
||||
a.container = container.NewBorder(
|
||||
container.NewHBox(util.NewHSpace(6), a.titleDisp, sortVbox, layout.NewSpacer(), searchVbox, util.NewHSpace(12)),
|
||||
container.NewHBox(util.NewHSpace(6), a.titleDisp, sortVbox, layout.NewSpacer(), a.filterBtn, searchVbox, util.NewHSpace(12)),
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
@@ -154,7 +158,7 @@ func (a *AlbumsPage) Reload() {
|
||||
if a.searchText != "" {
|
||||
a.doSearch(a.searchText)
|
||||
} else {
|
||||
iter := a.lm.AlbumsIter(backend.AlbumSortOrder(a.sortOrder.Selected), backend.AlbumFilter{})
|
||||
iter := a.lm.AlbumsIter(backend.AlbumSortOrder(a.sortOrder.Selected), a.filter)
|
||||
a.grid.Reset(widgets.NewGridViewAlbumIterator(iter))
|
||||
a.grid.Refresh()
|
||||
}
|
||||
@@ -190,7 +194,7 @@ func (a *AlbumsPage) doSearch(query string) {
|
||||
|
||||
func (a *AlbumsPage) onSortOrderChanged(order string) {
|
||||
a.cfg.SortOrder = a.sortOrder.Selected
|
||||
iter := a.lm.AlbumsIter(backend.AlbumSortOrder(order), backend.AlbumFilter{})
|
||||
iter := a.lm.AlbumsIter(backend.AlbumSortOrder(order), a.filter)
|
||||
a.grid.Reset(widgets.NewGridViewAlbumIterator(iter))
|
||||
if a.searchText == "" {
|
||||
a.container.Objects[0] = a.grid
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package dialogs
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"unicode"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/dweymouth/supersonic/backend"
|
||||
"github.com/dweymouth/supersonic/ui/widgets"
|
||||
)
|
||||
|
||||
type AlbumFilterDialog struct {
|
||||
widget.BaseWidget
|
||||
|
||||
OnDismissed func()
|
||||
|
||||
filter *backend.AlbumFilter
|
||||
container *fyne.Container
|
||||
}
|
||||
|
||||
func NewAlbumFilterDialog(filter *backend.AlbumFilter) *AlbumFilterDialog {
|
||||
a := &AlbumFilterDialog{filter: filter}
|
||||
a.ExtendBaseWidget(a)
|
||||
|
||||
// setup min and max year filters
|
||||
yearValidator := func(curText string, r rune) bool {
|
||||
return unicode.IsDigit(r) && len(curText) <= 3
|
||||
}
|
||||
minYear := widgets.NewTextRestrictedEntry(yearValidator)
|
||||
minYear.OnChanged = func(yearStr string) {
|
||||
if i, err := strconv.Atoi(yearStr); err == nil {
|
||||
a.filter.MinYear = i
|
||||
}
|
||||
}
|
||||
if filter.MinYear > 0 {
|
||||
minYear.Text = strconv.Itoa(filter.MinYear)
|
||||
}
|
||||
maxYear := widgets.NewTextRestrictedEntry(yearValidator)
|
||||
maxYear.OnChanged = func(yearStr string) {
|
||||
if i, err := strconv.Atoi(yearStr); err == nil {
|
||||
a.filter.MaxYear = i
|
||||
}
|
||||
}
|
||||
if filter.MaxYear > 0 {
|
||||
maxYear.Text = strconv.Itoa(filter.MaxYear)
|
||||
}
|
||||
|
||||
var isNotFavorite *widget.Check
|
||||
// setup is favorite/not favorite filters
|
||||
isFavorite := widget.NewCheck("Is favorite", func(fav bool) {
|
||||
if fav {
|
||||
isNotFavorite.SetChecked(false)
|
||||
}
|
||||
a.filter.ExcludeUnfavorited = fav
|
||||
})
|
||||
isNotFavorite = widget.NewCheck("Is not favorite", func(fav bool) {
|
||||
if fav {
|
||||
isFavorite.SetChecked(false)
|
||||
}
|
||||
a.filter.ExcludeFavorited = fav
|
||||
})
|
||||
|
||||
a.container = container.NewVBox(
|
||||
container.NewHBox(widget.NewLabel("Year from"), minYear, widget.NewLabel("to"), maxYear),
|
||||
isFavorite,
|
||||
isNotFavorite,
|
||||
)
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *AlbumFilterDialog) CreateRenderer() fyne.WidgetRenderer {
|
||||
return widget.NewSimpleRenderer(a.container)
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package widgets
|
||||
|
||||
import (
|
||||
"github.com/dweymouth/supersonic/backend"
|
||||
"github.com/dweymouth/supersonic/res"
|
||||
"github.com/dweymouth/supersonic/ui/theme"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
type FavoriteButton struct {
|
||||
widget.Button
|
||||
|
||||
IsFavorited bool
|
||||
}
|
||||
|
||||
func NewFavoriteButton(onTapped func()) *FavoriteButton {
|
||||
f := &FavoriteButton{
|
||||
Button: widget.Button{
|
||||
OnTapped: onTapped,
|
||||
Icon: res.ResHeartOutlineInvertPng,
|
||||
},
|
||||
}
|
||||
f.ExtendBaseWidget(f)
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *FavoriteButton) Tapped(e *fyne.PointEvent) {
|
||||
f.IsFavorited = !f.IsFavorited
|
||||
f.Button.Tapped(e)
|
||||
f.Refresh()
|
||||
}
|
||||
|
||||
func (f *FavoriteButton) Refresh() {
|
||||
if f.IsFavorited {
|
||||
f.Icon = theme.FavoriteIcon
|
||||
} else {
|
||||
f.Icon = theme.NotFavoriteIcon
|
||||
}
|
||||
f.Button.Refresh()
|
||||
}
|
||||
|
||||
type AlbumFilterButton struct {
|
||||
widget.Button
|
||||
|
||||
filter *backend.AlbumFilter
|
||||
|
||||
dialogConstructor func(*backend.AlbumFilter) fyne.CanvasObject
|
||||
dialog *widget.PopUp
|
||||
}
|
||||
|
||||
func NewAlbumFilterButton(filter *backend.AlbumFilter, dialogConstructor func(*backend.AlbumFilter) fyne.CanvasObject) *AlbumFilterButton {
|
||||
a := &AlbumFilterButton{
|
||||
filter: filter,
|
||||
dialogConstructor: dialogConstructor,
|
||||
Button: widget.Button{
|
||||
Icon: theme.AlbumIcon,
|
||||
},
|
||||
}
|
||||
a.OnTapped = a.showFilterDialog
|
||||
a.ExtendBaseWidget(a)
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *AlbumFilterButton) showFilterDialog() {
|
||||
if a.dialog == nil {
|
||||
a.dialog = widget.NewModalPopUp(a.dialogConstructor(a.filter), fyne.CurrentApp().Driver().CanvasForObject(a))
|
||||
}
|
||||
a.dialog.Show()
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package widgets
|
||||
|
||||
import (
|
||||
"github.com/dweymouth/supersonic/res"
|
||||
"github.com/dweymouth/supersonic/ui/theme"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
type FavoriteButton struct {
|
||||
widget.Button
|
||||
|
||||
IsFavorited bool
|
||||
}
|
||||
|
||||
func NewFavoriteButton(onTapped func()) *FavoriteButton {
|
||||
f := &FavoriteButton{
|
||||
Button: widget.Button{
|
||||
OnTapped: onTapped,
|
||||
Icon: res.ResHeartOutlineInvertPng,
|
||||
},
|
||||
}
|
||||
f.ExtendBaseWidget(f)
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *FavoriteButton) Tapped(e *fyne.PointEvent) {
|
||||
f.IsFavorited = !f.IsFavorited
|
||||
f.Button.Tapped(e)
|
||||
f.Refresh()
|
||||
}
|
||||
|
||||
func (f *FavoriteButton) Refresh() {
|
||||
if f.IsFavorited {
|
||||
f.Icon = theme.FavoriteIcon
|
||||
} else {
|
||||
f.Icon = theme.NotFavoriteIcon
|
||||
}
|
||||
f.Button.Refresh()
|
||||
}
|
||||
Reference in New Issue
Block a user