124 lines
4.2 KiB
C#
124 lines
4.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using JD.Application.View.TrackItems;
|
|
using JD.Audio.Annotations;
|
|
using JD.Collections;
|
|
using JD.Collections.Extensions;
|
|
using JD.Sequencers.Controls;
|
|
using TeaBox;
|
|
|
|
namespace JD.Application.View.Tracks
|
|
{
|
|
/// <summary>
|
|
/// Responsible of creating a track item corresponding to each item (model) in the provided collection.
|
|
/// </summary>
|
|
public class TrackItemSynchronizer<TModel, TView>
|
|
where TModel : EditableAnnotation
|
|
where TView : AnnotationTrackItem
|
|
{
|
|
#region Variables
|
|
|
|
private readonly Dictionary<TModel, TView> _modelToViewDictionary = new Dictionary<TModel, TView>();
|
|
private readonly Converter<TModel, TView> _createViewFromModel;
|
|
private readonly Predicate<TModel> _includeModel;
|
|
|
|
private readonly Track _view;
|
|
private readonly IAnnotationList<TModel> _annotationCollection;
|
|
|
|
#endregion
|
|
|
|
#region Constructor
|
|
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
public TrackItemSynchronizer(Track view, IAnnotationList<TModel> annotationCollection, Converter<TModel, TView> createViewFromModel, Predicate<TModel> includeModel)
|
|
{
|
|
_view = view;
|
|
_createViewFromModel = createViewFromModel;
|
|
_includeModel = includeModel ?? (model => true);
|
|
_annotationCollection = annotationCollection;
|
|
_annotationCollection.CollectionChanged += model_CollectionChanged;
|
|
_annotationCollection.ForEach(model => Register(model));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
private TView Register(TModel model)
|
|
{
|
|
TView view = null;
|
|
|
|
if (_includeModel(model))
|
|
{
|
|
view = _createViewFromModel(model);
|
|
view.ParentCollection = _annotationCollection;
|
|
|
|
_modelToViewDictionary.Add(model, view);
|
|
_view.Children.Add(view);
|
|
_view.Invalidate();
|
|
}
|
|
return view;
|
|
}
|
|
|
|
private void Unregister(TModel model)
|
|
{
|
|
TView view;
|
|
|
|
if (_modelToViewDictionary.TryGetValue(model, out view) && view != null)
|
|
{
|
|
if (view.Selected)
|
|
{
|
|
_view.TrackView.Selection.Remove(view);
|
|
}
|
|
|
|
_modelToViewDictionary.Remove(model);
|
|
_view.Children.Remove(view);
|
|
_view.Invalidate();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Each time the source collection is modified, the corresponding items are added and removed.
|
|
/// </summary>
|
|
private void model_CollectionChanged(object sender, CollectionChangedEventArgs<TModel> e)
|
|
{
|
|
if (e.Action == CollectionChangeAction.ItemChanged)
|
|
{
|
|
TView view;
|
|
bool contains = _modelToViewDictionary.TryGetValue(e.Item, out view);
|
|
|
|
if (contains)
|
|
{
|
|
view.Time = e.Item.Time;
|
|
}
|
|
|
|
// Happens when a comment change its type for example
|
|
if (contains != _includeModel(e.Item))
|
|
{
|
|
Unregister(e.Item);
|
|
view = Register(e.Item);
|
|
if (view != null)
|
|
{
|
|
// We assume that changing the type of the event implies that it was selected in the view
|
|
// so we restore it.
|
|
// For example, when using the arrow keys to change the track of annotations,
|
|
// this makes sure that the annotations are selected after chaning tracks.
|
|
_view.TrackView?.Selection.Add(view);
|
|
}
|
|
}
|
|
}
|
|
|
|
e.Synchronize(_annotationCollection, model => Register(model), Unregister);
|
|
|
|
if (e.Action == CollectionChangeAction.ItemAdded && _includeModel(e.Item))
|
|
{
|
|
// On the adding of a new item, we select it.
|
|
_view.TrackView?.Selection.Select(_modelToViewDictionary[e.Item]);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|