using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Windows.Forms; using JD.Application.View.TrackItems; using JD.Audio.Annotations; using JD.Sequencers.Controls; namespace JD.Application.View.Tracks { /// /// Base class for wave tracks that paints the song parts behing the track. /// public class WaveTrackBase : Track { private AnnotationCollection _annotations; private int _minimumHeight = 24; private int _maximumHeight = int.MaxValue; /// /// True when the items does overlap the maximum height of the track /// private int _annotationOverflows; public WaveTrackBase() { } public WaveTrackBase(AnnotationCollection annotations) { _annotations = annotations; } public virtual AnnotationCollection Annotations { get { return _annotations; } set { _annotations = value; } } public int MinimumHeight { get { return _minimumHeight; } set { _minimumHeight = value; Height = value; } } public int MaximumHeight { get { return _maximumHeight; } set { _maximumHeight = value; } } public override void ComputeChildBounds(Graphics graphics) { List rectangles = new List(); _annotationOverflows = 0; int height = MinimumHeight; var items = Children.OfType().OrderBy(item => item.Time.Value * 1); if (_maximumHeight < items.FirstOrDefault()?.Height*2) { ArrangeItemsOnSingleRow(graphics, items); return; } foreach (var trackItem in items) { trackItem.UpdatePosition(graphics, rectangles); rectangles.Add(trackItem.RelativeBounds); // Clean the used space, we do not need to consider it anymore var currentX = trackItem.RelativeBounds.X; rectangles.RemoveAll(rect => rect.Right < currentX); int newHeight = -trackItem.RelativeBounds.Y; trackItem.ShowLabel = newHeight <= _maximumHeight - trackItem.Height; if (!trackItem.ShowLabel) { _annotationOverflows = Math.Max(_annotationOverflows, trackItem.Height + 1); var bounds = trackItem.RelativeBounds; bounds.Y = -Height; trackItem.RelativeBounds = bounds; } height = Math.Max(height, newHeight); } Height = Math.Min(height, MaximumHeight); } private void ArrangeItemsOnSingleRow(Graphics graphics, IEnumerable items) { AnnotationTrackItem previousItem = null; var noSpace = new List(); foreach (var item in items) { item.UpdatePosition(graphics, noSpace); item.ShowLabel = true; if (previousItem != null && previousItem.Bounds.IntersectsWith(item.Bounds)) { previousItem.ShowLabel = false; } previousItem = item; } } public override void FinalizeChildBounds(Graphics graphics) { foreach (var trackItem in Children.OfType()) { var bounds = trackItem.RelativeBounds; bounds.Y += Bounds.Bottom; trackItem.Bounds = bounds; } } protected override void AlignTrackItemBounds(TrackItem item) { // Items are repositionned automatically on paint. } protected override void OnPaintBackground(PaintEventArgs e) { if (_annotationOverflows > 0) { var rect = Bounds; rect.Y -= 1; // To make sure the gradient is inside the bounds of the track. rect.Height = _annotationOverflows; using (var brush = new LinearGradientBrush(rect, Color.FromArgb(200, 0, 0, 0), Color.FromArgb(30, 0, 0, 0), LinearGradientMode.Vertical)) { e.Graphics.FillRectangle(brush, rect); } } // No background color. // base.OnPaintBackground(e); } } }