JD2022-TU1/main/tools/framework/JD.Application.TeaBox/View/Tracks/WaveTrackBase.cs

150 lines
No EOL
4.6 KiB
C#

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
{
/// <summary>
/// Base class for wave tracks that paints the song parts behing the track.
/// </summary>
public class WaveTrackBase : Track
{
private AnnotationCollection _annotations;
private int _minimumHeight = 24;
private int _maximumHeight = int.MaxValue;
/// <summary>
/// True when the items does overlap the maximum height of the track
/// </summary>
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<Rectangle> rectangles = new List<Rectangle>();
_annotationOverflows = 0;
int height = MinimumHeight;
var items = Children.OfType<AnnotationTrackItem>().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<AnnotationTrackItem> items)
{
AnnotationTrackItem previousItem = null;
var noSpace = new List<Rectangle>();
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<AnnotationTrackItem>())
{
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);
}
}
}