From: shivamv Date: Wed, 15 Sep 2021 12:43:58 +0000 (+0530) Subject: Adding Selector, SearchView and related classes X-Git-Tag: submit/tizen/20210915.141722~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=62541d33b384f34bf1aada1583f20c98956cf657;p=profile%2Fiot%2Fapps%2Fdotnet%2Fmusic-player.git Adding Selector, SearchView and related classes Change-Id: I167e50821bdb28d9e0e8289ddce34dee58e98292 Signed-off-by: shivamv --- diff --git a/music-player/Models/Album.cs b/music-player/Models/Album.cs index 455e32d..ecffa2e 100755 --- a/music-player/Models/Album.cs +++ b/music-player/Models/Album.cs @@ -20,6 +20,7 @@ namespace MusicPlayer.Models text = AlbumDataProvider.GetAlbumArtFromTracks(album.Id); } AlbumArtPath = text; + IsSelected = false; } private string albumName; @@ -65,5 +66,13 @@ namespace MusicPlayer.Models SetProperty(ref albumArtPath, thumb); } } + + private bool isSelected; + + public bool IsSelected + { + get => isSelected; + set => SetProperty(ref isSelected, value); + } } } diff --git a/music-player/Models/Artist.cs b/music-player/Models/Artist.cs index 20e9ff4..27d73f3 100755 --- a/music-player/Models/Artist.cs +++ b/music-player/Models/Artist.cs @@ -17,6 +17,7 @@ namespace MusicPlayer.Models TrackCount = ArtistDataProvider.GetArtistTrackCount(artistName).ToString(); TotalCount = AlbumCount + " / " + TrackCount; AlbumArtPath = ArtistDataProvider.GetArtistAlbumArtPath(artistName); + IsSelected = false; } private string artistName; @@ -74,5 +75,13 @@ namespace MusicPlayer.Models SetProperty(ref albumArtPath, thumb); } } + + private bool isSelected; + + public bool IsSelected + { + get => isSelected; + set => SetProperty(ref isSelected, value); + } } } diff --git a/music-player/Models/SearchGroup.cs b/music-player/Models/SearchGroup.cs new file mode 100755 index 0000000..acafdbb --- /dev/null +++ b/music-player/Models/SearchGroup.cs @@ -0,0 +1,19 @@ +using System.Collections.ObjectModel; + +namespace MusicPlayer.Models +{ + class SearchGroup : ObservableCollection + { + public SearchGroup() + { + //this is required for Activator.CreateInstance in ListViewModel + } + + public SearchGroup(string count) + { + DataCount = count; + } + + public string DataCount { get; set; } + } +} diff --git a/music-player/Models/SearchModel.cs b/music-player/Models/SearchModel.cs new file mode 100755 index 0000000..d9057ab --- /dev/null +++ b/music-player/Models/SearchModel.cs @@ -0,0 +1,68 @@ +using MusicPlayer.Common; + +namespace MusicPlayer.Models +{ + class SearchModel : PropertyNotifier + { + public SearchModel() + { + //this is required for Activator.CreateInstance in ListViewModel + } + + public SearchModel(Artist artist =null, MusicAlbum musicAlbum = null, Track track= null, int type =0) + { + AlbumDetail = musicAlbum; + ArtistDetail = artist; + TrackDetail = track; + ItemType = type; + if(type ==0) + { + Thumbnail = artist.AlbumArtPath; + Title = artist.ArtistName; + SubTitle = ""; + } + else if (type == 1) + { + Thumbnail = musicAlbum.AlbumArtPath; + Title = musicAlbum.AlbumName; + SubTitle = musicAlbum.ArtistName; + } + else if (type == 2) + { + Thumbnail = track.ThumbnailPath; + Title = track.TrackTitle; + SubTitle = track.ArtistName; + } + } + + private string thumbnail; + + public string Thumbnail + { + get => thumbnail; + set => SetProperty(ref thumbnail, value); + } + + private string title; + + public string Title + { + get => title; + set => SetProperty(ref title, value); + } + + private string subTitle; + + public string SubTitle + { + get => subTitle; + set => SetProperty(ref subTitle, value); + } + + public int ItemType { get; set; } + + public MusicAlbum AlbumDetail { get; set; } + public Artist ArtistDetail { get; set; } + public Track TrackDetail { get; set; } + } +} diff --git a/music-player/Models/Track.cs b/music-player/Models/Track.cs index 1435eb8..d611cb3 100755 --- a/music-player/Models/Track.cs +++ b/music-player/Models/Track.cs @@ -20,6 +20,7 @@ namespace MusicPlayer.Models Duration = TimeSpan.FromMilliseconds(audioInfo.Duration).ToString(AppConstants.TimeFormat); ThumbnailPath = audioInfo.ThumbnailPath; FilePath = audioInfo.Path; + IsSelected = false; } private string trackTitle; @@ -95,7 +96,15 @@ namespace MusicPlayer.Models public string FilePath { get => filePath; - set { filePath = value; } + set => filePath = value; + } + + private bool isSelected; + + public bool IsSelected + { + get => isSelected; + set => SetProperty(ref isSelected, value); } } } diff --git a/music-player/ViewModels/SearchViewModel.cs b/music-player/ViewModels/SearchViewModel.cs new file mode 100755 index 0000000..ff967a2 --- /dev/null +++ b/music-player/ViewModels/SearchViewModel.cs @@ -0,0 +1,136 @@ +using System.Collections.Specialized; +using System.Collections.Generic; +using MusicPlayer.Models; +using MusicPlayer.Common; +using MusicPlayer.Core; + +namespace MusicPlayer.ViewModels +{ + using Album = Tizen.Content.MediaContent.Album; + using AudioInfo = Tizen.Content.MediaContent.AudioInfo; + class SearchViewModel : PropertyNotifier + { + public SearchViewModel() + { + List artistList = ArtistDataProvider.CurrentArtistList(); + List albumList = AlbumDataProvider.CurrentAlbumList(); + List trackList = TrackDataProvider.CurrentTrackList(); + ArtistViewModelInSearch = new ArtistViewModel(); + AlbumViewModelInSearch = new AlbumViewModel(); + TrackViewModelInSearch = new TrackViewModel(); + + GroupListViewModel = new ListViewModel(); + + if(artistList.Count >0) + { + SearchGroup searchGroup = new SearchGroup(ArtistViewModelInSearch.ArtistCount); + ListViewModel searchListViewModel = new ListViewModel(); + foreach (Artist artist in ArtistViewModelInSearch.ListViewModel) + searchListViewModel.Add(new SearchModel(artist, null, null, 0)); + foreach (SearchModel item in searchListViewModel) + searchGroup.Add(item); + + GroupListViewModel.Add(searchGroup); + } + if (albumList.Count > 0) + { + SearchGroup searchGroup = new SearchGroup(AlbumViewModelInSearch.AlbumCount); + ListViewModel searchListViewModel = new ListViewModel(); + foreach (MusicAlbum musicAlbum in AlbumViewModelInSearch.ListViewModel) + searchListViewModel.Add(new SearchModel(null, musicAlbum, null, 1)); + foreach (SearchModel item in searchListViewModel) + searchGroup.Add(item); + + GroupListViewModel.Add(searchGroup); + } + if (trackList.Count > 0) + { + SearchGroup searchGroup = new SearchGroup(TrackViewModelInSearch.TrackCount); + ListViewModel searchListViewModel = new ListViewModel(); + foreach (Track track in TrackViewModelInSearch.ListViewModel) + searchListViewModel.Add(new SearchModel(null, null, track, 2)); + foreach (SearchModel item in searchListViewModel) + searchGroup.Add(item); + + GroupListViewModel.Add(searchGroup); + } + } + + public ListViewModel GroupListViewModel { get; set; } + + public ArtistViewModel ArtistViewModelInSearch { get; set; } + + public AlbumViewModel AlbumViewModelInSearch { get; set; } + + public TrackViewModel TrackViewModelInSearch { get; set; } + + public void UpdateSearchViewModel(string searchText) + { + ArtistViewModelInSearch.ListViewModel.Clear(); + AlbumViewModelInSearch.ListViewModel.Clear(); + TrackViewModelInSearch.ListViewModel.Clear(); + List artistList; + List albumList; + List trackList; + if (!string.IsNullOrEmpty(searchText)) + { + artistList = ArtistDataProvider.GetSearchedArtistList(searchText); + albumList = AlbumDataProvider.GetSearchedAlbumList(searchText); + trackList = TrackDataProvider.GetSearchedTrackList(searchText); + } + else + { + artistList = ArtistDataProvider.CurrentArtistList(); + albumList = AlbumDataProvider.CurrentAlbumList(); + trackList = TrackDataProvider.CurrentTrackList(); + } + ArtistViewModelInSearch.ListViewModel.CreateData(artistList); + AlbumViewModelInSearch.ListViewModel.CreateData(albumList); + TrackViewModelInSearch.ListViewModel.CreateData(trackList); + + if(GroupListViewModel.Count >0) + GroupListViewModel.Clear(); + + if (artistList.Count > 0) + { + SearchGroup searchGroup = new SearchGroup(ArtistViewModelInSearch.ArtistCount); + ListViewModel searchListViewModel = new ListViewModel(); + foreach (Artist artist in ArtistViewModelInSearch.ListViewModel) + searchListViewModel.Add(new SearchModel(artist, null, null, 0)); + foreach (SearchModel item in searchListViewModel) + searchGroup.Add(item); + + GroupListViewModel.Add(searchGroup); + } + if (albumList.Count > 0) + { + SearchGroup searchGroup = new SearchGroup(AlbumViewModelInSearch.AlbumCount); + ListViewModel searchListViewModel = new ListViewModel(); + foreach (MusicAlbum musicAlbum in AlbumViewModelInSearch.ListViewModel) + searchListViewModel.Add(new SearchModel(null, musicAlbum, null, 1)); + foreach (SearchModel item in searchListViewModel) + searchGroup.Add(item); + + GroupListViewModel.Add(searchGroup); + } + if (trackList.Count > 0) + { + SearchGroup searchGroup = new SearchGroup(TrackViewModelInSearch.TrackCount); + ListViewModel searchListViewModel = new ListViewModel(); + foreach (Track track in TrackViewModelInSearch.ListViewModel) + searchListViewModel.Add(new SearchModel(null, null, track, 2)); + foreach (SearchModel item in searchListViewModel) + searchGroup.Add(item); + + GroupListViewModel.Add(searchGroup); + } + } + + public void PlayTrack(Track currentTrack) + { + ListViewModel trackList = new ListViewModel(); + trackList.Add(currentTrack); + PlaybackHelper.Instance.PlayCurrent(trackList, currentTrack); + } + } +} diff --git a/music-player/ViewModels/SelectorViewModel.cs b/music-player/ViewModels/SelectorViewModel.cs new file mode 100755 index 0000000..04f93e3 --- /dev/null +++ b/music-player/ViewModels/SelectorViewModel.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using MusicPlayer.Models; +using MusicPlayer.Common; + +namespace MusicPlayer.ViewModels +{ + class SelectorViewModel : PropertyNotifier where T : new() + { + public SelectorViewModel(ListViewModel viewModel) + { + listViewModel = viewModel; + SelectedCount = "0"; + TotalCount = ListViewModel.Count; + } + + private readonly ListViewModel listViewModel; + + public ListViewModel ListViewModel => listViewModel; + + private string selectedCount; + public string SelectedCount + { + get => selectedCount; + set + { + string text = string.Equals(value, "0") ? "Select Items" : value + " Selected"; + SetProperty(ref selectedCount, text); + } + } + + public int TotalCount { get; set; } + + public List TrackList { get; set; } + + public int ShareMediaList(List shareList) + { + int tracksShared = TrackDataProvider.ShareTrackList(shareList); + Tizen.Log.Debug(AppConstants.LogTag, "Shared track count: " + tracksShared); + return tracksShared; + } + } +} diff --git a/music-player/Views/SearchView.cs b/music-player/Views/SearchView.cs new file mode 100755 index 0000000..44b713a --- /dev/null +++ b/music-player/Views/SearchView.cs @@ -0,0 +1,316 @@ +using System; +using Tizen.NUI.Components; +using Tizen.NUI.BaseComponents; +using Tizen.NUI; +using Tizen.NUI.Binding; +using MusicPlayer.Common; +using MusicPlayer.Models; +using MusicPlayer.ViewModels; +using MusicPlayer.Views.Utils; + +namespace MusicPlayer.Views +{ + class SearchView : View + { + private CollectionView collectionView; + private View topView; + private bool noItemFound; + private View noItemView; + private TextField textField; + private Button backButton; + private Button crossButton; + private View searchBox; + private TextLabel searchLabel; + + private SearchViewModel viewModel; + + public event EventHandler LaunchDetailView; + + public SearchView(SearchViewModel viewModel) : base() + { + this.viewModel = viewModel; + noItemFound = false; + noItemView = null; + WidthResizePolicy = ResizePolicyType.FillToParent; + HeightResizePolicy = ResizePolicyType.FillToParent; + BackgroundColor = UIColors.HEXEEEFF1; + Layout = new FlexLayout() + { + Direction = FlexLayout.FlexDirection.Column, + Padding = new Extents(64, 64, 0, 0), + }; + AddTopView(); + AddTopViewElements(); + AddSearchBox(); + AddCollectionView(); + Window.Instance.Add(this); + } + + private void AddTopView() + { + topView = new View() + { + BackgroundColor = UIColors.HEXEEEFF1, + Size2D = new Size2D(Window.Instance.WindowSize.Width - 128, 120), + Position2D = new Position2D(64, 0), + Layout = new FlexLayout + { + Direction = FlexLayout.FlexDirection.Row, + ItemsAlignment = FlexLayout.AlignmentType.Center, + }, + }; + base.Add(topView); + FlexLayout.SetFlexGrow(topView, 0); + FlexLayout.SetFlexShrink(topView, 0); + } + + private void AddTopViewElements() + { + ButtonStyle buttonStyle = new ButtonStyle() + { + Icon = new ImageViewStyle() + { + ResourceUrl = Resources.GetImagePath() + "back.png", + }, + IsSelectable = false, + IsEnabled = true, + }; + + backButton = new Button(buttonStyle) + { + Size2D = new Size2D(48, 48), + Margin = new Extents(0, 24, 0, 0), + }; + topView.Add(backButton); + backButton.Clicked += BackButtonClicked; + + searchLabel = new TextLabel() + { + Size2D = new Size2D(960, 48), + Text = "Search", + TextColor = UIColors.HEX001447, + PixelSize = 36, + FontFamily = "BreezeSans", + Margin = new Extents(0, 32, 0, 0), + }; + topView.Add(searchLabel); + } + + private void AddSearchBox() + { + searchBox = new View() + { + Size2D = new Size2D(648, 60), + Margin = new Extents(0, 32, 0, 0), + BackgroundImage = Resources.GetImagePath() + "search_box_bg.png", + Layout = new FlexLayout() + { + Direction = FlexLayout.FlexDirection.Row, + ItemsAlignment = FlexLayout.AlignmentType.Center, + Justification = FlexLayout.FlexJustification.FlexStart, + }, + }; + ButtonStyle searchButtonStyle = new ButtonStyle() + { + Icon = new ImageViewStyle() + { + ResourceUrl = Resources.GetImagePath() + "search_icon.png", + }, + IsSelectable = false, + IsEnabled = true, + }; + Button searchButton = new Button(searchButtonStyle) + { + Size2D = new Size2D(40, 40), + Margin = new Extents(24, 0, 10, 10), + Position2D = new Position2D(24, 10), + }; + textField = new TextField() + { + Size2D = new Size2D(460, 40), + BackgroundColor = Color.White, + Position2D = new Position2D(88, 10), + Margin = new Extents(24, 0, 10, 10), + TextColor = UIColors.HEX001447, + PlaceholderText = "Type Here", + PlaceholderTextFocused = "Search music", + }; + textField.TextChanged += TextFieldTextChanged; + + ButtonStyle crossButtonStyle = new ButtonStyle() + { + Icon = new ImageViewStyle() + { + ResourceUrl = Resources.GetImagePath() + "cross_button.png", + }, + IsSelectable = true, + IsEnabled = true, + }; + + crossButton = new Button(crossButtonStyle) + { + Size2D = new Size2D(48, 48), + Margin = new Extents(24, 0, 6, 6), + Position2D = new Position2D(572, 6), + }; + crossButton.Clicked += CrossButtonClicked; + + searchBox.Add(searchButton); + searchBox.Add(textField); + searchBox.Add(crossButton); + crossButton.Hide(); + topView.Add(searchBox); + } + + private void TextFieldTextChanged(object sender, TextField.TextChangedEventArgs e) + { + string searchText = e.TextField.Text; + if (string.IsNullOrEmpty(searchText)) + { + crossButton.Hide(); + crossButton.IsSelectable = false; + } + else + { + crossButton.Show(); + crossButton.IsSelectable = true; + } + viewModel.UpdateSearchViewModel(searchText); + UpdateSearchView(); + } + + private void CrossButtonClicked(object sender, ClickedEventArgs e) + { + textField.Text = ""; + } + + private void BackButtonClicked(object sender, ClickedEventArgs e) + { + Window.Instance.Remove(this); + } + + private void AddCollectionView() + { + collectionView = new CollectionView() + { + Size2D = new Size2D(1792, 108), + BackgroundImage = Resources.GetImagePath() + "list_view_bg.png", + Padding = new Extents(0, 0, 0, 0), + ItemsLayouter = new LinearLayouter(), + ItemTemplate = new DataTemplate(() => + { + ListItemLayout layout = new ListItemLayout(); + layout.Padding = new Extents(0, 0, 0, 0); + layout.Margin = new Extents(0, 0, 0, 0); + layout.Icon.SetBinding(ImageView.ResourceUrlProperty, "Thumbnail"); + layout.TitleLabel.SetBinding(TextLabel.TextProperty, "Title"); + layout.SubtitleLabel.SetBinding(TextLabel.TextProperty, "SubTitle"); + return layout; + }), + GroupHeaderTemplate = new DataTemplate(() => + { + DefaultTitleItem group = new DefaultTitleItem(); + group.WidthSpecification = 1792; + group.Padding = new Extents(0, 0, 0, 0); + group.Margin = new Extents(0, 0, 0, 0); + group.Label.SetBinding(TextLabel.TextProperty, "DataCount"); + group.Label.HorizontalAlignment = HorizontalAlignment.Begin; + group.Label.VerticalAlignment = VerticalAlignment.Center; + return group; + }), + IsGrouped = true, + ScrollingDirection = ScrollableBase.Direction.Vertical, + HeightSpecification = LayoutParamPolicies.WrapContent, + SelectionMode = ItemSelectionMode.Single, + }; + base.Add(collectionView); + FlexLayout.SetFlexGrow(collectionView, 1); + FlexLayout.SetFlexShrink(collectionView, 1); + collectionView.ItemsSource = viewModel.GroupListViewModel; + collectionView.SelectionChanged += OnItemSelection; + } + + private void OnItemSelection(object sender, SelectionChangedEventArgs e) + { + object selectedObject = collectionView.SelectedItem; + if (selectedObject is SearchModel) + { + Window.Instance.Remove(this); + SearchModel searchModel = (SearchModel)selectedObject; + if (searchModel.ItemType == 0) + { + Artist currentArtist = searchModel.ArtistDetail; + SubContentViewAddEventArgs artistDetailViewArgs = new SubContentViewAddEventArgs(SubContentViewType.ArtistDetails, currentArtist.ArtistName, currentArtist); + LaunchDetailView?.Invoke(this, artistDetailViewArgs); + } + else if (searchModel.ItemType == 1) + { + MusicAlbum currentAlbum = searchModel.AlbumDetail; + SubContentViewAddEventArgs albumDetailViewArgs = new SubContentViewAddEventArgs(SubContentViewType.AlbumDetails, currentAlbum.AlbumName, currentAlbum); + LaunchDetailView?.Invoke(this, albumDetailViewArgs); + } + else if (searchModel.ItemType == 2) + { + Track currentTrack = searchModel.TrackDetail; + viewModel.PlayTrack(currentTrack); + } + } + } + + public void UpdateSearchView() + { + if (viewModel.GroupListViewModel.Count > 0) + { + if (noItemFound) + { + base.Remove(noItemView); + base.Add(collectionView); + } + noItemFound = false; + } + else + { + if (noItemView == null) + { + noItemView = new View() + { + BackgroundColor = UIColors.HEXEEEFF1, + WidthSpecification = LayoutParamPolicies.MatchParent, + HeightResizePolicy = ResizePolicyType.FillToParent, + Layout = new FlexLayout + { + Direction = FlexLayout.FlexDirection.Column, + ItemsAlignment = FlexLayout.AlignmentType.Center, + Justification = FlexLayout.FlexJustification.FlexStart, + Padding = new Extents(0, 0, 40, 0), + } + }; + ImageView noResultsIcon = new ImageView() + { + BackgroundColor = UIColors.HEXEEEFF1, + ResourceUrl = Resources.GetImagePath() + "no_results_found.png", + Size2D = new Size2D(264, 292), + }; + noItemView.Add(noResultsIcon); + TextLabel textLabel = new TextLabel() + { + Size2D = new Size2D(1124, 36), + Text = "No results found", + TextColor = UIColors.HEX001447, + PixelSize = 28, + FontFamily = "BreezeSans", + HorizontalAlignment = HorizontalAlignment.Center, + Margin = new Extents(0, 0, 32, 0), + }; + noItemView.Add(textLabel); + } + if (!noItemFound) + { + base.Remove(collectionView); + base.Add(noItemView); + } + noItemFound = true; + } + } + } +} diff --git a/music-player/Views/SelectListLayout.cs b/music-player/Views/SelectListLayout.cs new file mode 100755 index 0000000..9693db6 --- /dev/null +++ b/music-player/Views/SelectListLayout.cs @@ -0,0 +1,157 @@ +using Tizen.NUI.Components; +using Tizen.NUI.BaseComponents; +using Tizen.NUI; +using MusicPlayer.Common; + +namespace MusicPlayer.Views +{ + class SelectListLayout : RecyclerViewItem + { + private static int Width = 1792; + private static int Height = 108; + + private const int BoxSize = 36; + private const int IconSize = 64; + private const int LayoutMargin = 16; + private const int LayoutPadding = 32; + private const int SeperatorHeight = 1; + private const int LeftPadding = 64; + private const int x = 0; + + private CheckBox checkBox; + private View itemSeperator; + private TextLabel titleLabel; + private TextLabel subtitleLabel; + private ImageView icon; + + public SelectListLayout(int width = 1792, int height = 108) : base() + { + base.OnInitialize(); + base.IsCreateByXaml = true; + Width = width; + Height = height; + WidthSpecification = Width; + HeightSpecification = Height; + + // to show the rounded rect of the bg + BackgroundColor = Color.Transparent; + + StringSelector iconURL = new StringSelector() + { + Disabled = Resources.GetImagePath() + "check_off.png", + DisabledSelected = Resources.GetImagePath() + "check_on.png", + }; + + checkBox = new CheckBox() + { + Size2D = new Size2D(BoxSize, BoxSize), + IsCreateByXaml = true, + Position2D = new Position2D(x, BoxSize), + IconURLSelector = iconURL, + IsSelected = false, + IsEnabled =false, + }; + + checkBox.Icon.Opacity = 1.0f; + checkBox.Icon.Size = new Size2D(BoxSize, BoxSize); + base.Add(checkBox); + + icon = new ImageView() + { + WidthSpecification = IconSize, + HeightSpecification = IconSize, + IsCreateByXaml = true, + Position2D = new Position2D(x + BoxSize + LayoutPadding, ((Height / 2) - (IconSize / 2))), + }; + base.Add(icon); + + itemSeperator = new View() + { + WidthSpecification = (Width - (2 * LeftPadding)), + HeightSpecification = SeperatorHeight, + ExcludeLayouting = true, + Position2D = new Position2D(x, Height - SeperatorHeight), + BackgroundColor = UIColors.ItemSeperator, + }; + base.Add(itemSeperator); + + titleLabel = new TextLabel() + { + WidthSpecification = (Width - (2 * LeftPadding) - IconSize - 2 * LayoutPadding - BoxSize), + HeightSpecification = 40, + TextColor = UIColors.HEX001447, + PixelSize = 32, + FontFamily = "BreezeSans", + VerticalAlignment = VerticalAlignment.Center, + IsCreateByXaml = true, + Position2D = new Position2D((x + IconSize + 2 * LayoutPadding + BoxSize), LayoutMargin), + }; + base.Add(titleLabel); + + subtitleLabel = new TextLabel() + { + WidthSpecification = (Width - (2 * LeftPadding) - IconSize - 2* LayoutPadding - BoxSize), + HeightSpecification = 36, + TextColor = UIColors.HEX001447, + PixelSize = 28, + FontFamily = "BreezeSans", + VerticalAlignment = VerticalAlignment.Center, + IsCreateByXaml = true, + Position2D = new Position2D((x + IconSize + 2 * LayoutPadding + BoxSize), LayoutMargin + 40) + }; + base.Add(subtitleLabel); + IsCreateByXaml = true; + IsSelected = false; + } + + public ImageView Icon + { + get => icon; + } + public TextLabel TitleLabel + { + get => titleLabel; + } + public TextLabel SubtitleLabel + { + get => subtitleLabel; + } + + public CheckBox Checkbox + { + get => checkBox; + } + + protected override void Dispose(DisposeTypes type) + { + if (Disposed) + { + return; + } + if (type == DisposeTypes.Explicit) + { + base.Remove(itemSeperator); + itemSeperator?.Dispose(); + itemSeperator = null; + + base.Remove(checkBox); + checkBox?.Dispose(); + checkBox = null; + + base.Remove(icon); + icon?.Dispose(); + icon = null; + + base.Remove(titleLabel); + titleLabel?.Dispose(); + titleLabel = null; + + base.Remove(subtitleLabel); + subtitleLabel?.Dispose(); + subtitleLabel = null; + } + + base.Dispose(type); + } + } +} diff --git a/music-player/Views/SelectorView.cs b/music-player/Views/SelectorView.cs new file mode 100755 index 0000000..db4b5ad --- /dev/null +++ b/music-player/Views/SelectorView.cs @@ -0,0 +1,440 @@ +using System.Collections; +using System.Collections.Specialized; +using System.Collections.Generic; +using MusicPlayer.ViewModels; +using Tizen.NUI.Components; +using Tizen.NUI.BaseComponents; +using Tizen.NUI; +using Tizen.NUI.Binding; +using MusicPlayer.Common; +using MusicPlayer.Models; +using MusicPlayer.Core; +using MusicPlayer.Views.Utils; + +namespace MusicPlayer.Views +{ + // This class need to be refactored for better design + // Need to create BaseSelectorView classs + // And Derive PlaylistSelectorView, TrackSelectorView, AlbumSelectorView, ArtistSelectorView for better code quality + using AudioInfo = Tizen.Content.MediaContent.AudioInfo; + class SelectorView : View where T : new() + { + private const int LayoutPadding = 64; + private const int TextLabelHeight = 48; + private const int TextButtonWidth = 260; + private const int LayoutMargin = 36; + + private View topView; + private View selAllView; + private TextLabel selectedCountLabel; + private CheckBox selAllButton; + private Button cancelButton; + private Button doneButton; + private CollectionView collectionView; + + int itemCount = 0; + public List selectedItemList; + + private SelectorViewModel viewModel; + private OperationViewType currentViewType; + + + public SelectorView(OperationViewType viewType, SelectorViewModel viewModel) : base() + { + currentViewType = viewType; + selectedItemList = new List(); + this.viewModel = viewModel; + BindingContext = viewModel; + BackgroundColor = UIColors.HEXEEEFF1; + WidthResizePolicy = ResizePolicyType.FillToParent; + HeightResizePolicy = ResizePolicyType.FillToParent; + + Layout = new FlexLayout() + { + Direction = FlexLayout.FlexDirection.Column, + ItemsAlignment = FlexLayout.AlignmentType.FlexStart, + Justification = FlexLayout.FlexJustification.FlexStart, + }; + + topView = AddTopView(); + AddSelectCountLabel(); + AddButtons(); + selAllView = AddSelAllView(); + AddSelAllViewElements(); + collectionView = AddCollectionView(); + itemCount = 0; + + Window.Instance.Add(this); + } + + public List SelectedItemList => selectedItemList; + + private Button CreateButton(string url, int x, int y) + { + ButtonStyle buttonStyle = new ButtonStyle() + { + Text = new TextLabelStyle() + { + Text = url, + PixelSize = 28, + FontFamily = "BreezeSans", + TextColor = UIColors.HEX000C2B, + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + }, + IsSelectable = false, + }; + + Button button = new Button(buttonStyle) + { + Size2D = new Size2D(TextButtonWidth, TextLabelHeight), + Position2D = new Position2D(x, y), + IsEnabled = false, + IsSelectable = true, + }; + return button; + } + + private View AddTopView() + { + View topView = new View() + { + WidthSpecification = Window.Instance.WindowSize.Width, + HeightSpecification = 120, + Layout = new FlexLayout() + { + Direction = FlexLayout.FlexDirection.Row, + Padding = new Extents(LayoutPadding, LayoutPadding, LayoutMargin, LayoutMargin), + }, + }; + base.Add(topView); + return topView; + } + + private void AddSelectCountLabel() + { + selectedCountLabel = new TextLabel() + { + Size2D = new Size2D(1192, TextLabelHeight), + Position2D = new Position2D(LayoutPadding, 0), + PixelSize = 36, + FontFamily = "BreezeSans", + TextColor = UIColors.HEX000209, + HorizontalAlignment = HorizontalAlignment.Begin, + VerticalAlignment = VerticalAlignment.Center, + Ellipsis = true, + }; + selectedCountLabel.SetBinding(TextLabel.TextProperty, "SelectedCount"); + topView.Add(selectedCountLabel); + } + + private void AddButtons() + { + cancelButton = CreateButton("Cancel", Window.Instance.WindowSize.Width - LayoutPadding - 2 * TextButtonWidth -40, LayoutMargin); + cancelButton.Margin = new Extents(40, 0, 0, 0); + cancelButton.IsEnabled = true; + topView.Add(cancelButton); + cancelButton.Clicked += (object o, ClickedEventArgs args) => + { + OnCancel(); + }; + + doneButton = CreateButton("Done", Window.Instance.WindowSize.Width - LayoutPadding - TextButtonWidth, LayoutMargin); + doneButton.Margin = new Extents(40, 0, 0, 0); + topView.Add(doneButton); + doneButton.Clicked += (object o, ClickedEventArgs args) => + { + OnDone(); + }; + } + + private void OnCancel() + { + ClearSelectionAndRemove(); + } + + private void OnDone() + { + Tizen.Log.Error(AppConstants.LogTag, "OnDone, Operation Type is: " + currentViewType.ToString()); + if (currentViewType == OperationViewType.Share) + { + int sharedItems = viewModel.ShareMediaList(SelectedItemList); + Tizen.Log.Debug(AppConstants.LogTag, "Total shared items: " + sharedItems); + } + else + { + if (typeof(T) == typeof(PlaylistModel)) + { + int playlistDeleted = PlaylistManager.Instance.DeletePlaylists(SelectedItemList); + Tizen.Log.Debug(AppConstants.LogTag, "Total playlist deleted: " + playlistDeleted); + } + else + { + int tracksDeleted = TrackDataProvider.DeleteTrackList(SelectedItemList); + Tizen.Log.Debug(AppConstants.LogTag, "Total tracks deleted: " + tracksDeleted); + } + } + ClearSelectionAndRemove(); + } + + private void ClearSelectionAndRemove() + { + collectionView.SelectedItems.Clear(); + Window.Instance.Remove(this); + } + + private View AddSelAllView() + { + View selAllView = new View() + { + WidthSpecification = Window.Instance.WindowSize.Width - 2 * LayoutPadding, + HeightSpecification = 108, + Position2D = new Position2D(LayoutPadding,120), + Margin = new Extents(LayoutPadding,LayoutPadding,0,40), + BackgroundImage = Resources.GetImagePath() + "list_view_bg.png", + }; + base.Add(selAllView); + return selAllView; + } + + private void AddSelAllViewElements() + { + selAllButton = new CheckBox() + { + Size2D = new Size2D(36, 36), + Position2D = new Position2D(LayoutPadding, LayoutMargin), + Margin = new Extents(LayoutPadding, 32, LayoutMargin, LayoutMargin), + }; + selAllView.Add(selAllButton); + selAllButton.Clicked += OnSelAllClicked; + + TextLabel selAll = new TextLabel() + { + Text = "Select All", + Size2D = new Size2D(1596, 40), + Margin = new Extents(0,LayoutPadding,34,34), + Position2D = new Position2D(LayoutPadding+36+32, 34), + PixelSize = 32, + FontFamily = "BreezeSans", + TextColor = UIColors.HEX001447, + HorizontalAlignment = HorizontalAlignment.Begin, + VerticalAlignment = VerticalAlignment.Center, + Ellipsis = true, + }; + selAllView.Add(selAll); + } + + private void OnSelAllClicked(object sender, ClickedEventArgs e) + { + if(selAllButton.IsSelected) + { + doneButton.IsEnabled = true; + foreach (object item in collectionView.ItemsSource) + { + if (!collectionView.SelectedItems.Contains(item)) + { + collectionView.SelectedItems.Add(item); + } + } + itemCount = viewModel.TotalCount; + } + else + { + doneButton.IsEnabled = false; + collectionView.SelectedItems.Clear(); + itemCount = 0; + selectedItemList.Clear(); + } + viewModel.SelectedCount = itemCount.ToString(); + Tizen.Log.Debug(AppConstants.LogTag, "Total tracks selected " + selectedItemList.Count); + } + + public void CancelSelection() + { + collectionView.SelectedItems.Clear(); + Window.Instance.Remove(this); + } + + public void DoneSelection() + { + collectionView.SelectedItems.Clear(); + Window.Instance.Remove(this); + } + + private CollectionView AddCollectionView() + { + CollectionView collectionView = new CollectionView() + { + Size2D = new Size2D(1792, 108), + Margin = new Extents(LayoutPadding, LayoutPadding, 0, 0), + BackgroundImage = Resources.GetImagePath() + "list_view_bg.png", + ItemsLayouter = new LinearLayouter(), + ScrollingDirection = ScrollableBase.Direction.Vertical, + HeightSpecification = LayoutParamPolicies.WrapContent, + SelectionMode = ItemSelectionMode.Multiple, + }; + base.Add(collectionView); + FlexLayout.SetFlexGrow(collectionView, 1); + FlexLayout.SetFlexShrink(collectionView, 1); + if (typeof(T) == typeof(MusicAlbum)) + { + collectionView.ItemTemplate = new DataTemplate(() => + { + SelectListLayout layout = new SelectListLayout(); + layout.Icon.SetBinding(ImageView.ResourceUrlProperty, "AlbumArtPath"); + layout.TitleLabel.SetBinding(TextLabel.TextProperty, "AlbumName"); + layout.SubtitleLabel.SetBinding(TextLabel.TextProperty, "ArtistName"); + layout.Checkbox.SetBinding(Button.IsSelectedProperty, "IsSelected"); + return layout; + }); + collectionView.ItemsSource = viewModel.ListViewModel; + } + else if (typeof(T) == typeof(Track)) + { + collectionView.ItemTemplate = new DataTemplate(() => + { + SelectListLayout layout = new SelectListLayout(); + layout.Icon.SetBinding(ImageView.ResourceUrlProperty, "ThumbnailPath"); + layout.TitleLabel.SetBinding(TextLabel.TextProperty, "TrackTitle"); + layout.SubtitleLabel.SetBinding(TextLabel.TextProperty, "ArtistName"); + layout.Checkbox.SetBinding(Button.IsSelectedProperty, "IsSelected"); + return layout; + }); + collectionView.ItemsSource = viewModel.ListViewModel; + } + else if (typeof(T) == typeof(Artist)) + { + collectionView.ItemTemplate = new DataTemplate(() => + { + SelectListLayout layout = new SelectListLayout(); + layout.Icon.SetBinding(ImageView.ResourceUrlProperty, "AlbumArtPath"); + layout.TitleLabel.SetBinding(TextLabel.TextProperty, "ArtistName"); + layout.SubtitleLabel.SetBinding(TextLabel.TextProperty, "TotalCount"); + layout.Checkbox.SetBinding(Button.IsSelectedProperty, "IsSelected"); + return layout; + }); + collectionView.ItemsSource = viewModel.ListViewModel; + } + else if(typeof(T) == typeof(PlaylistModel)) + { + collectionView.ItemTemplate = new DataTemplate(() => + { + SelectListLayout layout = new SelectListLayout(); + layout.Icon.SetBinding(ImageView.ResourceUrlProperty, "PlaylistThumbnailPath"); + layout.TitleLabel.SetBinding(TextLabel.TextProperty, "PlaylistName"); + layout.SubtitleLabel.SetBinding(TextLabel.TextProperty, "PlaylistTrackCount"); + layout.Checkbox.SetBinding(Button.IsSelectedProperty, "PlaylistIsSelected"); + return layout; + }); + collectionView.ItemsSource = viewModel.ListViewModel; + } + collectionView.SelectionChanged += SelectionEvent; + return collectionView; + } + + public void SelectionEvent(object sender, SelectionChangedEventArgs ev) + { + List oldSel = new List(ev.PreviousSelection); + List newSel = new List(ev.CurrentSelection); + + foreach (object item in oldSel) + { + if (item != null && !newSel.Contains(item)) + { + itemCount--; + if (item is Track) + { + Track trackItem = (Track)item; + trackItem.IsSelected = false; + selectedItemList.Remove(trackItem.Id); + } + else if (item is Artist) + { + Artist artistItem = (Artist)item; + artistItem.IsSelected = false; + string text = artistItem.ArtistName; + if (text == "Unknown") + text = ""; + List artistTrackList = ArtistDataProvider.GetArtistTrackList(text); + foreach (AudioInfo track in artistTrackList) + { + selectedItemList.Remove(track.Id); + } + } + else if (item is MusicAlbum) + { + MusicAlbum albumItem = (MusicAlbum)item; + albumItem.IsSelected = false; + List albumTrackList = AlbumDataProvider.GetAlbumTrackList(albumItem.Id); + foreach (AudioInfo track in albumTrackList) + { + selectedItemList.Remove(track.Id); + } + } + else if(item is PlaylistModel) + { + PlaylistModel playlistItem = (PlaylistModel)item; + playlistItem.PlaylistIsSelected = false; + selectedItemList.Remove(playlistItem.PlaylistId.ToString()); + } + } + } + + foreach (object item in newSel) + { + if (item != null && !oldSel.Contains(item)) + { + itemCount++; + if (item is Track) + { + Track trackItem = (Track)item; + trackItem.IsSelected = true; + selectedItemList.Add(trackItem.Id); + } + else if (item is Artist) + { + Artist artistItem = (Artist)item; + artistItem.IsSelected = true; + string text = artistItem.ArtistName; + if (text == "Unknown") + text = ""; + List artistTrackList = ArtistDataProvider.GetArtistTrackList(text); + foreach (AudioInfo track in artistTrackList) + { + selectedItemList.Add(track.Id); + } + } + else if (item is MusicAlbum) + { + MusicAlbum albumItem = (MusicAlbum)item; + albumItem.IsSelected = true; + List albumTrackList = AlbumDataProvider.GetAlbumTrackList(albumItem.Id); + foreach (AudioInfo track in albumTrackList) + { + selectedItemList.Add(track.Id); + } + } + else if (item is PlaylistModel) + { + PlaylistModel playlistItem = (PlaylistModel)item; + playlistItem.PlaylistIsSelected = true; + selectedItemList.Add(playlistItem.PlaylistId.ToString()); + } + } + } + + viewModel.SelectedCount = itemCount.ToString(); + + if (itemCount == 0) + doneButton.IsEnabled = false; + else + doneButton.IsEnabled = true; + + Tizen.Log.Debug(AppConstants.LogTag, "Total tracks selected " + selectedItemList.Count); + if (itemCount == viewModel.TotalCount) + selAllButton.IsSelected = true; + else + selAllButton.IsSelected = false; + } + } +}