270 lines
6.5 KiB
C#
270 lines
6.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Specialized;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace BizHawk.Client.Common
|
|
{
|
|
/// <summary>
|
|
/// Represents a TasMovie Marker
|
|
/// A marker is a tagged frame with a message
|
|
/// </summary>
|
|
public class TasMovieMarker
|
|
{
|
|
public TasMovieMarker(int frame, string message = "")
|
|
{
|
|
Frame = frame;
|
|
Message = message;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parses a Marker from a line of text
|
|
/// </summary>
|
|
public TasMovieMarker(string line)
|
|
{
|
|
var split = line.Split('\t');
|
|
Frame = int.Parse(split[0]);
|
|
Message = split[1];
|
|
}
|
|
|
|
public virtual int Frame { get; private set; }
|
|
|
|
public virtual string Message { get; set; }
|
|
|
|
public override string ToString()
|
|
{
|
|
return Frame.ToString() + '\t' + Message;
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return this.Frame.GetHashCode();
|
|
}
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
if (obj == null)
|
|
{
|
|
return false;
|
|
}
|
|
else if (obj is TasMovieMarker)
|
|
{
|
|
return this.Frame == (obj as TasMovieMarker).Frame;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static bool operator ==(TasMovieMarker marker, int frame)
|
|
{
|
|
return marker.Frame == frame;
|
|
}
|
|
|
|
public static bool operator !=(TasMovieMarker marker, int frame)
|
|
{
|
|
return marker.Frame != frame;
|
|
}
|
|
}
|
|
|
|
public class TasMovieMarkerList : List<TasMovieMarker>
|
|
{
|
|
private readonly TasMovie _movie;
|
|
|
|
public TasMovieMarkerList(TasMovie movie)
|
|
{
|
|
_movie = movie;
|
|
}
|
|
|
|
public TasMovieMarkerList DeepClone()
|
|
{
|
|
TasMovieMarkerList ret = new TasMovieMarkerList(_movie);
|
|
for (int i = 0; i < this.Count; i++)
|
|
ret.Add(new TasMovieMarker(this[i].Frame, this[i].Message));
|
|
|
|
return ret;
|
|
}
|
|
|
|
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
|
|
|
private void OnListChanged(NotifyCollectionChangedAction action)
|
|
{
|
|
if (CollectionChanged != null)
|
|
{
|
|
//TODO Allow different types
|
|
CollectionChanged.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
|
}
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
var sb = new StringBuilder();
|
|
foreach (var marker in this)
|
|
{
|
|
sb.AppendLine(marker.ToString());
|
|
}
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
public new void Add(TasMovieMarker item)
|
|
{
|
|
var existingItem = this.FirstOrDefault(m => m.Frame == item.Frame);
|
|
if (existingItem != null)
|
|
{
|
|
if (existingItem.Message != item.Message)
|
|
{
|
|
_movie.ChangeLog.AddMarkerChange(item, item.Frame, existingItem.Message);
|
|
existingItem.Message = item.Message;
|
|
OnListChanged(NotifyCollectionChangedAction.Replace);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_movie.ChangeLog.AddMarkerChange(item);
|
|
base.Add(item);
|
|
this.Sort((m1, m2) => m1.Frame.CompareTo(m2.Frame));
|
|
OnListChanged(NotifyCollectionChangedAction.Add);
|
|
}
|
|
}
|
|
|
|
public void Add(int frame, string message)
|
|
{
|
|
Add(new TasMovieMarker(frame, message));
|
|
}
|
|
|
|
public new void AddRange(IEnumerable<TasMovieMarker> collection)
|
|
{
|
|
bool endBatch = _movie.ChangeLog.BeginNewBatch("Add Markers", true);
|
|
foreach (TasMovieMarker m in collection)
|
|
{
|
|
Add(m);
|
|
}
|
|
if (endBatch)
|
|
_movie.ChangeLog.EndBatch();
|
|
}
|
|
|
|
public new void Insert(int index, TasMovieMarker item)
|
|
{
|
|
_movie.ChangeLog.AddMarkerChange(item);
|
|
base.Insert(index, item);
|
|
this.Sort((m1, m2) => m1.Frame.CompareTo(m2.Frame));
|
|
OnListChanged(NotifyCollectionChangedAction.Add);
|
|
}
|
|
|
|
public new void InsertRange(int index, IEnumerable<TasMovieMarker> collection)
|
|
{
|
|
bool endBatch = _movie.ChangeLog.BeginNewBatch("Add Markers", true);
|
|
foreach (TasMovieMarker m in collection)
|
|
_movie.ChangeLog.AddMarkerChange(m);
|
|
if (endBatch)
|
|
_movie.ChangeLog.EndBatch();
|
|
|
|
base.InsertRange(index, collection);
|
|
this.Sort((m1, m2) => m1.Frame.CompareTo(m2.Frame));
|
|
OnListChanged(NotifyCollectionChangedAction.Add);
|
|
}
|
|
|
|
public new void Remove(TasMovieMarker item)
|
|
{
|
|
if (item == null) // TODO: Don't do this.
|
|
return;
|
|
_movie.ChangeLog.AddMarkerChange(null, item.Frame, item.Message);
|
|
base.Remove(item);
|
|
OnListChanged(NotifyCollectionChangedAction.Remove);
|
|
}
|
|
|
|
public new int RemoveAll(Predicate<TasMovieMarker> match)
|
|
{
|
|
bool endBatch = _movie.ChangeLog.BeginNewBatch("Remove All Markers", true);
|
|
foreach (TasMovieMarker m in this)
|
|
{
|
|
if (match.Invoke(m))
|
|
_movie.ChangeLog.AddMarkerChange(null, m.Frame, m.Message);
|
|
}
|
|
if (endBatch)
|
|
_movie.ChangeLog.EndBatch();
|
|
|
|
int removeCount = base.RemoveAll(match);
|
|
if (removeCount > 0)
|
|
{
|
|
OnListChanged(NotifyCollectionChangedAction.Remove);
|
|
}
|
|
return removeCount;
|
|
}
|
|
|
|
public void Move(int fromFrame, int toFrame)
|
|
{
|
|
TasMovieMarker m = Get(fromFrame);
|
|
if (m == null) // TODO: Don't do this.
|
|
return;
|
|
_movie.ChangeLog.AddMarkerChange(m, m.Frame);
|
|
Insert(0, new TasMovieMarker(toFrame, m.Message));
|
|
Remove(m);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deletes all markers at or below the given start frame.
|
|
/// </summary>
|
|
/// <param name="startFrame">The first frame for markers to be deleted.</param>
|
|
/// <returns>Number of markers deleted.</returns>
|
|
public int TruncateAt(int startFrame)
|
|
{
|
|
int deletedCount = 0;
|
|
bool endBatch = _movie.ChangeLog.BeginNewBatch("Truncate Markers", true);
|
|
for (int i = Count - 1; i > -1; i--)
|
|
{
|
|
if (this[i].Frame >= startFrame)
|
|
{
|
|
_movie.ChangeLog.AddMarkerChange(null, this[i].Frame, this[i].Message);
|
|
RemoveAt(i);
|
|
deletedCount++;
|
|
}
|
|
}
|
|
if (endBatch)
|
|
_movie.ChangeLog.EndBatch();
|
|
if (deletedCount > 0)
|
|
{
|
|
OnListChanged(NotifyCollectionChangedAction.Remove);
|
|
}
|
|
return deletedCount;
|
|
}
|
|
|
|
public TasMovieMarker Previous(int currentFrame)
|
|
{
|
|
return this
|
|
.Where(m => m.Frame < currentFrame)
|
|
.OrderBy(m => m.Frame)
|
|
.LastOrDefault();
|
|
}
|
|
|
|
public TasMovieMarker PreviousOrCurrent(int currentFrame)
|
|
{
|
|
return this
|
|
.Where(m => m.Frame <= currentFrame)
|
|
.OrderBy(m => m.Frame)
|
|
.LastOrDefault();
|
|
}
|
|
|
|
public TasMovieMarker Next(int currentFrame)
|
|
{
|
|
return this
|
|
.Where(m => m.Frame > currentFrame)
|
|
.OrderBy(m => m.Frame)
|
|
.FirstOrDefault();
|
|
}
|
|
|
|
public bool IsMarker(int frame)
|
|
{
|
|
return this.Any(m => m == frame);
|
|
}
|
|
|
|
public TasMovieMarker Get(int frame)
|
|
{
|
|
return this.FirstOrDefault(m => m == frame);
|
|
}
|
|
}
|
|
}
|