public void Render(IGraphicsContext context) { lock (_locker) { if (_brushBackground == null) { _brushBackground = new BasicBrush(_backgroundColor); _penTransparent = new BasicPen(); _penBorder = new BasicPen(new BasicBrush(_borderColor), 1); _rectText = context.MeasureText("12345:678.90", new BasicRectangle(0, 0, Frame.Width, Frame.Height), "HelveticaNeue", 10); } } _density = context.Density; Frame = new BasicRectangle(0, 0, context.BoundsWidth, context.BoundsHeight); context.DrawRectangle(new BasicRectangle(0, 0, context.BoundsWidth, context.BoundsHeight), _brushBackground, _penTransparent); if (_audioFile == null || _audioFileLength == 0) return; // Check if scale type needs to be updated if (_lastWidth != ContentSize.Width) { _lastWidth = ContentSize.Width; CalculateScale(context.Density); } // Draw scale borders //Console.WriteLine("WaveFormScaleView - scaleType: {0} totalMinutes: {1} totalSeconds: {2} totalMinutesScaled: {3} totalSecondsScaled: {4}", scaleType.ToString(), totalMinutes, totalSeconds, totalMinutesScaled, totalSecondsScaled); context.SetPen(_penBorder); context.StrokeLine(new BasicPoint(0, ContentSize.Height - 1), new BasicPoint(ContentSize.Width, ContentSize.Height - 1)); int firstVisibleIndex = (int)Math.Floor(ContentOffset.X / _tickWidth); int lastVisibleIndex = firstVisibleIndex + (int)Math.Floor(context.BoundsWidth / _tickWidth); float tickX = -ContentOffset.X + (firstVisibleIndex * _tickWidth); int majorTickIndex = (int)Math.Ceiling(firstVisibleIndex / 10f); //for (int a = firstVisibleIndex; a < _tickCount; a++) for (int a = firstVisibleIndex; a < lastVisibleIndex; a++) { // Ignore ticks out of bounds bool isMajorTick = ((a % 10) == 0); if (tickX >= 0 && tickX <= Frame.Width) { //Console.WriteLine("####> WaveFormView - Scale - tick {0} x: {1} isMajorTick: {2} tickCount: {3}", a, tickX, isMajorTick, tickCount); if(isMajorTick) // //context.DrawLine(new BasicPoint(tickX, context.BoundsHeight - (context.BoundsHeight / 1.25f)), new BasicPoint(tickX, context.BoundsHeight), _penMajorTick); context.StrokeLine(new BasicPoint(tickX, 0), new BasicPoint(tickX, ContentSize.Height - 1)); else context.StrokeLine(new BasicPoint(tickX, ContentSize.Height - (ContentSize.Height / 6) - 1), new BasicPoint(tickX, ContentSize.Height - 1)); if (isMajorTick) { // Draw dashed traversal line for major ticks context.StrokeLine(new BasicPoint(tickX, ContentSize.Height - 1), new BasicPoint(tickX, ContentSize.Height - 1)); // Determine major scale text int minutes = 0; int seconds = 0; switch (_scaleType) { case WaveFormScaleType._10minutes: minutes = majorTickIndex * 10; seconds = 0; break; case WaveFormScaleType._5minutes: minutes = majorTickIndex * 5; seconds = 0; break; case WaveFormScaleType._2minutes: minutes = majorTickIndex * 2; seconds = 0; break; case WaveFormScaleType._1minute: minutes = majorTickIndex; seconds = 0; break; case WaveFormScaleType._30seconds: minutes = (int)Math.Floor(majorTickIndex / _scaleMultiplier); seconds = (majorTickIndex % _scaleMultiplier == 0) ? 0 : 30; break; case WaveFormScaleType._10seconds: minutes = (int)Math.Floor(majorTickIndex / _scaleMultiplier); seconds = ((int)Math.Floor(majorTickIndex % _scaleMultiplier)) * 10; break; case WaveFormScaleType._5seconds: minutes = (int)Math.Floor(majorTickIndex / _scaleMultiplier); seconds = ((int)Math.Floor(majorTickIndex % _scaleMultiplier)) * 5; break; case WaveFormScaleType._1second: minutes = (int)Math.Floor(majorTickIndex / _scaleMultiplier); seconds = (int)Math.Floor(majorTickIndex % _scaleMultiplier); break; } // Draw text at every major tick (minute count) string scaleMajorTitle = string.Format("{0}:{1:00}", minutes, seconds); //float y = ContentSize.Height - (ContentSize.Height/12f) - _rectText.Height - (0.5f * context.Density); float y = 3 * context.Density;//ContentSize.Height - _rectText.Height - (10 * context.Density); context.DrawText(scaleMajorTitle, new BasicPoint(tickX + (4 * context.Density), y), _textColor, FontFace, FontSize); } } if(isMajorTick) majorTickIndex++; tickX += _tickWidth; } }
private void DrawDebugInformation(IGraphicsContext context) { // Display debug information if enabled if (_displayDebugInformation) { // Build debug string var sbDebug = new StringBuilder(); sbDebug.AppendLine("Line Count: " + _items.Count.ToString()); sbDebug.AppendLine("Line Height: " + _songCache.LineHeight.ToString()); sbDebug.AppendLine("Lines Fit In Height: " + _songCache.NumberOfLinesFittingInControl.ToString()); sbDebug.AppendLine("Total Width: " + _songCache.TotalWidth); sbDebug.AppendLine("Total Height: " + _songCache.TotalHeight); sbDebug.AppendLine("Scrollbar Offset Y: " + _songCache.ScrollBarOffsetY); sbDebug.AppendLine("HScrollbar Maximum: " + HorizontalScrollBar.Maximum.ToString()); sbDebug.AppendLine("HScrollbar LargeChange: " + HorizontalScrollBar.LargeChange.ToString()); sbDebug.AppendLine("HScrollbar Value: " + HorizontalScrollBar.Value.ToString()); sbDebug.AppendLine("VScrollbar Maximum: " + VerticalScrollBar.Maximum.ToString()); sbDebug.AppendLine("VScrollbar LargeChange: " + VerticalScrollBar.LargeChange.ToString()); sbDebug.AppendLine("VScrollbar Value: " + VerticalScrollBar.Value.ToString()); // Measure string //stringFormat.Trimming = StringTrimming.Word; //stringFormat.LineAlignment = StringAlignment.Near; //SizeF sizeDebugText = g.MeasureString(sbDebug.ToString(), fontDefault, _columns[0].Width - 1, stringFormat); var sizeDebugText = context.MeasureText(sbDebug.ToString(), new BasicRectangle(0, 0, _columns[0].Width, 40), _theme.FontName, _theme.FontSize); var rect = new BasicRectangle(0, 0, _columns[0].Width - 1, sizeDebugText.Height); // Draw background var brush = new BasicBrush(new BasicColor(200, 0, 0)); var penTransparent = new BasicPen(); context.DrawRectangle(rect, brush, penTransparent); // Draw string context.DrawText(sbDebug.ToString(), rect, new BasicColor(255, 255, 255), _theme.FontName, _theme.FontSize); } }
private void DrawStatus(IGraphicsContext context, string status) { //Console.WriteLine("WaveFormControl - DrawStatus - status: {0}", status); context.DrawRectangle(Frame, new BasicBrush(_backgroundColor), new BasicPen()); var rectText = context.MeasureText(status, new BasicRectangle(0, 0, Frame.Width, 30), FontFace, FontSize); float x = (context.BoundsWidth - rectText.Width) / 2; float y = context.BoundsHeight / 2; context.DrawText(status, new BasicPoint(x, y), _textColor, FontFace, FontSize); }
private void DrawAlbumCoverZone(IGraphicsContext context, int row, AudioFile audioFile2, DrawCellState state) { var pen = new BasicPen(); var penTransparent = new BasicPen(); var brushGradient = new BasicGradientBrush(); var item = _items[row]; //string albumTitle = audioFile != null ? audioFile.AlbumTitle : state.CurrentAlbumTitle; // if this is an empty row, keep last album title // Check for an album title change (or the last item of the grid) if (state.CurrentAlbumArtKey == item.AlbumArtKey) return; state.CurrentAlbumArtKey = item.AlbumArtKey; int albumCoverStartIndex = 0; int albumCoverEndIndex = 0; // For displaying the album cover, we need to know how many songs of the same album are bundled together // Start by getting the start index for (int c = row; c > 0; c--) { var previousItem = _items[c]; if (previousItem.AlbumArtKey != item.AlbumArtKey) { albumCoverStartIndex = c + 1; break; } } // Find the end index for (int c = row + 1; c < _items.Count; c++) { var nextItem = _items[c]; // If the album title is different, this means we found the next album title if (nextItem.AlbumArtKey != item.AlbumArtKey) { albumCoverEndIndex = c - 1; break; } // If this is the last item of the grid... else if (c == _items.Count - 1) { albumCoverEndIndex = c; break; } } var audioFile = _items[albumCoverStartIndex].AudioFile; // Calculate y and height int scrollbarOffsetY = (_startLineNumber * _songCache.LineHeight) - VerticalScrollBar.Value; int y = ((albumCoverStartIndex - _startLineNumber) * _songCache.LineHeight) + _songCache.LineHeight + scrollbarOffsetY; // Calculate the height of the album cover zone (+1 on end index because the array is zero-based) int linesToCover = Math.Min(MinimumRowsPerAlbum, (albumCoverEndIndex + 1 - albumCoverStartIndex)); int albumCoverZoneHeight = linesToCover * _songCache.LineHeight; int heightWithPadding = Math.Min(albumCoverZoneHeight - (_theme.Padding * 2), _songCache.ActiveColumns[0].Width - (_theme.Padding * 2)); // Make sure the height is at least zero (not necessary to draw anything!) if (albumCoverZoneHeight > 0) { // Draw album cover background var rectAlbumCover = new BasicRectangle(0 - HorizontalScrollBar.Value, y, _songCache.ActiveColumns[0].Width, albumCoverZoneHeight); brushGradient = new BasicGradientBrush(_theme.AlbumCoverBackgroundColor, _theme.AlbumCoverBackgroundColor, 90); context.DrawRectangle(rectAlbumCover, brushGradient, penTransparent); // Measure available width for text int widthAvailableForText = _columns[0].Width - (_theme.Padding * 2); // Display titles depending on if an album art was found var rectAlbumCoverArt = new BasicRectangle(); var rectAlbumTitleText = new BasicRectangle(); var rectArtistNameText = new BasicRectangle(); var sizeAlbumTitle = new BasicRectangle(); var sizeArtistName = new BasicRectangle(); bool useAlbumArtOverlay = false; bool displayArtistNameAndAlbumTitle = false; // Try to extract image from cache IBasicImage imageAlbumCover = null; SongGridViewImageCache cachedImage = null; try { cachedImage = _imageCache.FirstOrDefault(x => x.Key == item.AlbumArtKey); } catch (Exception ex) { Tracing.Log(ex); } if (cachedImage != null) imageAlbumCover = cachedImage.Image; // Album art not found in cache; try to find an album cover in one of the file if (cachedImage == null) { try { // Check if the album cover is already in the pile bool albumCoverFound = false; foreach (var arg in _workerUpdateAlbumArtPile) { // Match by file path if (arg.AudioFile.FilePath.ToUpper() == audioFile.FilePath.ToUpper()) { albumCoverFound = true; } } // Add to the pile only if the album cover isn't already in it if (!albumCoverFound) { // Add item to update album art worker pile var arg = new SongGridViewBackgroundWorkerArgument(); arg.AudioFile = audioFile; arg.LineIndex = row; arg.RectAlbumArt = new BasicRectangle(0, 0, heightWithPadding, heightWithPadding); _workerUpdateAlbumArtPile.Add(arg); } } catch(Exception ex) { Console.WriteLine("SongGridViewControl - Failed to load cache image: {0}" , ex); } } // There are at least two lines; is there an album cover to display? if (imageAlbumCover == null) { // There is no album cover to display; display only text. // Set string format //stringFormat.Alignment = StringAlignment.Center; //stringFormat.Trimming = StringTrimming.EllipsisWord; sizeArtistName = context.MeasureText(audioFile.ArtistName, new BasicRectangle(0, 0, widthAvailableForText, heightWithPadding), _theme.FontNameAlbumArtTitle, _theme.FontSize + 2); sizeAlbumTitle = context.MeasureText(audioFile.AlbumTitle, new BasicRectangle(0, 0, widthAvailableForText, heightWithPadding), _theme.FontNameAlbumArtSubtitle, _theme.FontSize); // Display the album title at the top of the zome rectArtistNameText = new BasicRectangle(_theme.Padding - HorizontalScrollBar.Value, y + _theme.Padding, widthAvailableForText, heightWithPadding); rectAlbumTitleText = new BasicRectangle(_theme.Padding - HorizontalScrollBar.Value, y + _theme.Padding + sizeArtistName.Height, widthAvailableForText, heightWithPadding); displayArtistNameAndAlbumTitle = true; useAlbumArtOverlay = true; } else { // There is an album cover to display with more than 2 lines. // Set string format //stringFormat.Alignment = StringAlignment.Near; //stringFormat.Trimming = StringTrimming.EllipsisWord; float widthRemainingForText = _columns[0].Width - (_theme.Padding * 3) - heightWithPadding; sizeArtistName = context.MeasureText(audioFile.ArtistName, new BasicRectangle(0, 0, widthRemainingForText, heightWithPadding), _theme.FontNameAlbumArtTitle, _theme.FontSize + 2); sizeAlbumTitle = context.MeasureText(audioFile.AlbumTitle, new BasicRectangle(0, 0, widthRemainingForText, heightWithPadding), _theme.FontNameAlbumArtSubtitle, _theme.FontSize); // Try to center the cover art + padding + max text width //float maxWidth = Math.Max(sizeArtistName.Width, sizeAlbumTitle.Width); float albumCoverX = _theme.Padding - 2; // (_columns[0].Width - heightWithPadding - _theme.Padding - _theme.Padding - maxWidth) / 2; float artistNameY = _theme.Padding + 1; // (albumCoverZoneHeight - sizeArtistName.Height - sizeAlbumTitle.Height) / 2; // Display the album title at the top of the zome rectArtistNameText = new BasicRectangle(albumCoverX + heightWithPadding + _theme.Padding - HorizontalScrollBar.Value, y + artistNameY, widthRemainingForText, heightWithPadding); rectAlbumTitleText = new BasicRectangle(albumCoverX + heightWithPadding + _theme.Padding - HorizontalScrollBar.Value, y + artistNameY + sizeArtistName.Height + (_theme.Padding / 8f), widthRemainingForText, heightWithPadding); rectAlbumCoverArt = new BasicRectangle(albumCoverX - HorizontalScrollBar.Value, y + _theme.Padding, heightWithPadding, heightWithPadding); displayArtistNameAndAlbumTitle = widthRemainingForText > 20; useAlbumArtOverlay = true; } // Display album cover if (imageAlbumCover != null) context.DrawImage(rectAlbumCoverArt, new BasicRectangle(0, 0, imageAlbumCover.ImageSize.Width, imageAlbumCover.ImageSize.Height), imageAlbumCover.Image); //context.DrawImage(rectAlbumCoverArt, new BasicRectangle(0, 0, rectAlbumCoverArt.Width, rectAlbumCoverArt.Height), imageAlbumCover.Image); // if (useAlbumArtOverlay) // { // // Draw artist name and album title background // var rectArtistNameBackground = new BasicRectangle(rectArtistNameText.X - (_theme.Padding / 2), rectArtistNameText.Y - (_theme.Padding / 4), sizeArtistName.Width + _theme.Padding, sizeArtistName.Height + (_theme.Padding / 2)); // var rectAlbumTitleBackground = new BasicRectangle(rectAlbumTitleText.X - (_theme.Padding / 2), rectAlbumTitleText.Y - (_theme.Padding / 4), sizeAlbumTitle.Width + _theme.Padding, sizeAlbumTitle.Height + (_theme.Padding / 2)); // var brushTextBackground = new BasicBrush(new BasicColor(0, 0, 0, 30)); // context.DrawRectangle(rectArtistNameBackground, brushTextBackground, penTransparent); // context.DrawRectangle(rectAlbumTitleBackground, brushTextBackground, penTransparent); // } if (displayArtistNameAndAlbumTitle) { context.DrawText(audioFile.ArtistName, rectArtistNameText, _theme.HeaderTextColor, _theme.FontNameAlbumArtTitle, _theme.FontSize + 2); context.DrawText(audioFile.AlbumTitle, rectAlbumTitleText, _theme.HeaderTextColor, _theme.FontNameAlbumArtSubtitle, _theme.FontSize); } // Draw horizontal line to distinguish albums // Part 1: Draw line over grid pen = new BasicPen(new BasicBrush(new BasicColor(180, 180, 180)), 1); context.DrawLine(new BasicPoint(_columns[0].Width, y), new BasicPoint(Frame.Width, y), pen); // Part 2: Draw line over album art zone, in a lighter color pen = new BasicPen(new BasicBrush(new BasicColor(115, 115, 115)), 1); context.DrawLine(new BasicPoint(0, y), new BasicPoint(_columns[0].Width, y), pen); } }