/// <summary> /// Imports playlist items as SongGridViewItems. /// </summary> /// <param name="playlist">Playlist</param> public void ImportPlaylist(Playlist playlist) { _mode = SongGridViewMode.Playlist; _items = new List<SongGridViewItem>(); foreach (var playlistItem in playlist.Items) { var item = new SongGridViewItem(); item.AudioFile = playlistItem.AudioFile; item.PlaylistItemId = playlistItem.Id; _items.Add(item); } // Reset scrollbar position VerticalScrollBar.Value = 0; _songCache = null; OnInvalidateVisual(); }
/// <summary> /// Creates a cache of values used for rendering the song grid view. /// Also sets scrollbar position, height, value, maximum, etc. /// </summary> public void InvalidateSongCache() { // Check if columns have been created if (_columns == null || _columns.Count == 0 || _items == null) return; // Create cache _songCache = new SongGridViewCache(); // Get active columns and order them _songCache.ActiveColumns = _columns.Where(x => x.Order >= 0).OrderBy(x => x.Order).ToList(); //// Create temporary bitmap/graphics objects to measure a string (to determine line height) //Bitmap bmpTemp = new Bitmap(200, 100); //Graphics g = Graphics.FromImage(bmpTemp); //SizeF sizeFont = g.MeasureString("QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm!@#$%^&*()", fontDefaultBold); //g.Dispose(); //g = null; //bmpTemp.Dispose(); //bmpTemp = null; string allChars = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm!@#$%^&*()"; //var rectText = context.MeasureText(allChars, new BasicRectangle(0, 0, 1000, 100), "Roboto", 12); var rectText = new BasicRectangle(0, 0, 100, 14); // Calculate the line height (try to measure the total possible height of characters using the custom or default font) _songCache.LineHeight = (int)rectText.Height + _theme.Padding; _songCache.TotalHeight = _songCache.LineHeight * _items.Count; // Check if the total active columns width exceed the width available in the control _songCache.TotalWidth = 0; for (int a = 0; a < _songCache.ActiveColumns.Count; a++) if (_songCache.ActiveColumns[a].Visible) _songCache.TotalWidth += _songCache.ActiveColumns[a].Width; // Calculate the number of lines visible (count out the header, which is one line height) _songCache.NumberOfLinesFittingInControl = (int)Math.Floor((double)(Frame.Height) / (double)(_songCache.LineHeight)); // Set vertical scrollbar dimensions //VerticalScrollBar.Top = _songCache.LineHeight; //VerticalScrollBar.Left = ClientRectangle.Width - VerticalScrollBar.Width; VerticalScrollBar.Minimum = 0; // Scrollbar maximum is the number of lines fitting in the screen + the remaining line which might be cut // by the control height because it's not a multiple of line height (i.e. the last line is only partly visible) int lastLineHeight = (int) (Frame.Height - (_songCache.LineHeight * _songCache.NumberOfLinesFittingInControl)); // Check width if (_songCache.TotalWidth > Frame.Width - VerticalScrollBar.Width) { // Set scrollbar values HorizontalScrollBar.Maximum = _songCache.TotalWidth; HorizontalScrollBar.SmallChange = 5; HorizontalScrollBar.LargeChange = (int) Frame.Width; HorizontalScrollBar.Visible = true; } // Check if the horizontal scrollbar needs to be turned off if (_songCache.TotalWidth <= Frame.Width - VerticalScrollBar.Width && HorizontalScrollBar.Visible) HorizontalScrollBar.Visible = false; // If there are less items than items fitting on screen... if (((_songCache.NumberOfLinesFittingInControl - 1) * _songCache.LineHeight) - HorizontalScrollBar.Height >= _songCache.TotalHeight) { // Disable the scrollbar VerticalScrollBar.Enabled = false; VerticalScrollBar.Value = 0; } else { VerticalScrollBar.Enabled = true; // Calculate the vertical scrollbar maximum int vMax = _songCache.LineHeight * (_items.Count - _songCache.NumberOfLinesFittingInControl + 1) - lastLineHeight; // Add the horizontal scrollbar height if visible if (HorizontalScrollBar.Visible) vMax += HorizontalScrollBar.Height; // Compensate for the header, and for the last line which might be truncated by the control height VerticalScrollBar.Maximum = vMax; VerticalScrollBar.SmallChange = _songCache.LineHeight; VerticalScrollBar.LargeChange = 1 + _songCache.LineHeight * 5; } // Calculate the scrollbar offset Y _songCache.ScrollBarOffsetY = (_startLineNumber * _songCache.LineHeight) - VerticalScrollBar.Value; // If both scrollbars need to be visible, the width and height must be changed if (HorizontalScrollBar.Visible && VerticalScrollBar.Visible) { // Cut 16 pixels HorizontalScrollBar.Width = (int) (Frame.Width - 16); VerticalScrollBar.Height = (int) (Frame.Height - (_songCache.LineHeight * 2) - 16); } else { VerticalScrollBar.Height = (int) (Frame.Height - (_songCache.LineHeight * 2)); } }
/// <summary> /// Imports audio files as SongGridViewItems. /// </summary> /// <param name="audioFiles">List of AudioFiles</param> public void ImportAudioFiles(List<AudioFile> audioFiles) { _mode = SongGridViewMode.AudioFile; _items = new List<SongGridViewItem>(); var albums = audioFiles.GroupBy(x => new { x.ArtistName, x.AlbumTitle }); foreach (var album in albums) { var songs = audioFiles.Where(x => x.ArtistName == album.Key.ArtistName && x.AlbumTitle == album.Key.AlbumTitle).ToArray(); foreach (var song in songs) { var item = new SongGridViewItem(); item.AudioFile = song; item.PlaylistItemId = Guid.NewGuid(); item.AlbumArtKey = album.Key.ArtistName + "_" + album.Key.AlbumTitle; _items.Add(item); } if (songs.Length < MinimumRowsPerAlbum) { for (int a = 0; a < MinimumRowsPerAlbum - songs.Length; a++) { var item = new SongGridViewItem(); item.IsEmptyRow = true; item.AlbumArtKey = album.Key.ArtistName + "_" + album.Key.AlbumTitle; _items.Add(item); } } } VerticalScrollBar.Value = 0; _songCache = null; OnInvalidateVisual(); }
public void MouseClick(float x, float y, MouseButtonType button, KeysHeld keysHeld) { bool controlNeedsToBeFullyInvalidated = false; bool controlNeedsToBePartiallyInvalidated = false; var partialRect = new BasicRectangle(); if (_columns == null || _songCache == null) return; // Show context menu strip if the button click is right and not the album art column if (button == MouseButtonType.Right && x > _columns[0].Width && y > _songCache.LineHeight) OnDisplayContextMenu(ContextMenuType.Item, x, y); int albumArtCoverWidth = _columns[0].Visible ? _columns[0].Width : 0; var columnResizing = _columns.FirstOrDefault(col => col.IsUserResizingColumn == true); int scrollbarOffsetY = (_startLineNumber * _songCache.LineHeight) - VerticalScrollBar.Value; // Check if the user has clicked on the header (for orderBy) if (y >= 0 && y <= _songCache.LineHeight && columnResizing == null && !IsColumnMoving) { // Check on what column the user has clicked int offsetX = 0; for (int a = 0; a < _songCache.ActiveColumns.Count; a++) { var column = _songCache.ActiveColumns[a]; if (column.Visible) { // Check if the mouse pointer is over this column if (x >= offsetX - HorizontalScrollBar.Value && x <= offsetX + column.Width - HorizontalScrollBar.Value) { if (button == MouseButtonType.Left && CanChangeOrderBy) { // Check if the column order was already set if (_orderByFieldName == column.FieldName) { // Reverse ascending/descending _orderByAscending = !_orderByAscending; } else { // Set order by field name _orderByFieldName = column.FieldName; _orderByAscending = true; } //_items = null; _songCache = null; // Raise column click event (if an event is subscribed) if (OnColumnClick != null) { var data = new SongGridViewColumnClickData(); data.ColumnIndex = a; OnColumnClick(data); } OnInvalidateVisual(); return; } else if (button == MouseButtonType.Right) { //// Refresh column visibility in menu before opening //foreach (ToolStripMenuItem menuItem in _menuColumns.Items) //{ // SongGridViewColumn menuItemColumn = _columns.FirstOrDefault(x => x.Title == menuItem.Tag.ToString()); // if (menuItemColumn != null) // menuItem.Checked = menuItemColumn.Visible; //} OnDisplayContextMenu(ContextMenuType.Header, x, y); } } offsetX += column.Width; } } } // Loop through visible lines to find the original selected items var tuple = GetStartIndexAndEndIndexOfSelectedRows(); int startIndex = tuple.Item1; int endIndex = tuple.Item2; // Make sure the indexes are set if (startIndex > -1 && endIndex > -1) { // Invalidate the original selected lines int startY = ((startIndex - _startLineNumber + 1) * _songCache.LineHeight) + scrollbarOffsetY; int endY = ((endIndex - _startLineNumber + 2) * _songCache.LineHeight) + scrollbarOffsetY; var newPartialRect = new BasicRectangle(albumArtCoverWidth - HorizontalScrollBar.Value, startY, Frame.Width - albumArtCoverWidth + HorizontalScrollBar.Value, endY - startY); partialRect.Merge(newPartialRect); controlNeedsToBePartiallyInvalidated = true; } // Reset selection (make sure SHIFT or CTRL isn't held down) if (!keysHeld.IsShiftKeyHeld && !keysHeld.IsCtrlKeyHeld) { // Make sure the mouse is over at least one item var mouseOverItem = _items.FirstOrDefault(item => item.IsMouseOverItem == true); if (mouseOverItem != null) ResetSelection(); } // Loop through visible lines to update the new selected items bool invalidatedNewSelection = false; for (int a = _startLineNumber; a < _startLineNumber + _numberOfLinesToDraw; a++) { // Check if mouse is over this item if (_items[a].IsMouseOverItem) { invalidatedNewSelection = true; // Check if SHIFT is held if (keysHeld.IsShiftKeyHeld) { // Find the start index of the selection int startIndexSelection = _lastItemIndexClicked; if (a < startIndexSelection) startIndexSelection = a; if (startIndexSelection < 0) startIndexSelection = 0; // Find the end index of the selection int endIndexSelection = _lastItemIndexClicked; if (a > endIndexSelection) endIndexSelection = a + 1; // Loop through items to selected for (int b = startIndexSelection; b < endIndexSelection; b++) _items [b].IsSelected = true; controlNeedsToBeFullyInvalidated = true; } // Check if CTRL is held else if(keysHeld.IsCtrlKeyHeld) { // Invert selection _items[a].IsSelected = !_items[a].IsSelected; var newPartialRect = new BasicRectangle(albumArtCoverWidth - HorizontalScrollBar.Value, ((a - _startLineNumber + 1) * _songCache.LineHeight) + scrollbarOffsetY, Frame.Width - albumArtCoverWidth + HorizontalScrollBar.Value, _songCache.LineHeight); partialRect.Merge(newPartialRect); controlNeedsToBePartiallyInvalidated = true; } else { // Set this item as the new selected item _items[a].IsSelected = true; var newPartialRect = new BasicRectangle(albumArtCoverWidth - HorizontalScrollBar.Value, ((a - _startLineNumber + 1) * _songCache.LineHeight) + scrollbarOffsetY, Frame.Width - albumArtCoverWidth + HorizontalScrollBar.Value, _songCache.LineHeight); partialRect.Merge(newPartialRect); controlNeedsToBePartiallyInvalidated = true; } // Set the last item clicked index _lastItemIndexClicked = a; break; } } // Raise selected item changed event (if an event is subscribed) if (invalidatedNewSelection && OnSelectedIndexChanged != null) { var data = new SongGridViewSelectedIndexChangedData(); OnSelectedIndexChanged(data); } if (controlNeedsToBeFullyInvalidated) OnInvalidateVisual(); else if (controlNeedsToBePartiallyInvalidated) OnInvalidateVisualInRect(partialRect); }