public static void StopTracking(this ITrackableObject source) { if (trackedObjects != null) { trackedObjects.Remove(source); } }
private static bool IsDeleted(ITrackableObject source, TrackingState tracker, List <ITrackableObject> deletedItems) { //If the parent object is deleted then no need to check children. if (tracker.Deleted) { deletedItems?.Add(tracker.TrackedObject); return(true); } bool hasDeletes = false; foreach (var property in tracker.UnmodifiedState) { if (property.Key.PropertyType.IsGenericType && property.Key.PropertyType.IsAssignableTo(typeof(System.Collections.IEnumerable))) { System.Collections.IEnumerable list = (System.Collections.IEnumerable)property.Value; foreach (object item in list) { ITrackableObject trackedItem = item as ITrackableObject; if (trackedItem != null) { if (IsDeleted(trackedItem, GetTracker(trackedItem), deletedItems)) { if (deletedItems == null) { return(true); } hasDeletes = true; } } } } } return(hasDeletes); }
public static bool IsDeleted(this ITrackableObject source, out IEnumerable <ITrackableObject> deletedItems) { TrackingState tracker = GetTracker(source); deletedItems = new List <ITrackableObject>(); return(IsDeleted(source, tracker, (List <ITrackableObject>)deletedItems)); }
private static bool IsNew(ITrackableObject source, TrackingState tracker) { //If the parent object is added then no need to check children. if (tracker.Added) { return(true); } foreach (var property in tracker.UnmodifiedState) { if (property.Key.PropertyType.IsGenericType && property.Key.PropertyType.IsAssignableTo(typeof(System.Collections.IEnumerable))) { System.Collections.IEnumerable list = (System.Collections.IEnumerable)property.Value; foreach (object item in list) { ITrackableObject trackedItem = item as ITrackableObject; if (trackedItem != null) { if (IsNew(trackedItem)) { return(true); } } } } } return(false); }
/// <summary> /// Determines if the current <see cref="Camera"/> instances contains the <see cref="ITrackableObject"/>. /// </summary> /// <param name="testObject">The <see cref="ITrackableObject"/> to test.</param> /// <param name="entirelyContained">If true, will only return true if the testObject is entirely contained in the <see cref="Camera.Bounds"/>, otherwise will return true if any part of the testObject is contained.</param> /// <returns>If entirelyContained is true, returns true only if the entire testObject is contained within <see cref="Camera.Bounds"/>. If entirelyContained is false, returns true if any part of the testObject is contained within <see cref="Camera.Bounds"/>.</returns> public bool Contains(ITrackableObject testObject, bool entirelyContained) { if (entirelyContained) { return(Bounds.Contains(new RectangleF(testObject.Position, testObject.Size))); } else { // We're only checking corner cases as we are assuming that the `testObject` is not *bigger* than the `Camera`. If it is, then that's a different issue. (We'll likely fix this in the future, just not today!) if (Bounds.Contains(testObject.Position)) { return(true); } if (Bounds.Contains(testObject.Position.X, testObject.Size.Height)) { return(true); } if (Bounds.Contains(testObject.Size.Width, testObject.Position.Y)) { return(true); } if (Bounds.Contains(testObject.Size.Width, testObject.Size.Height)) { return(true); } } return(false); }
public static void Undo(this ITrackableObject source) { TrackingState tracker = GetTracker(source); tracker.Deleted = false; tracker.Added = false; tracker.Print = false; foreach (var property in tracker.UnmodifiedState) { if (property.Value == null) { if (property.Key.GetValue(source) != null) { property.Key.SetValue(source, null); } } else { if (!property.Value.Equals(property.Key.GetValue(source))) { property.Key.SetValue(source, property.Value); } } } }
private static TrackingState GetTracker(ITrackableObject source) { TrackingState tracker; if (!trackedObjects.TryGetValue(source, out tracker)) { throw new InvalidOperationException("Unable to detect changes because object is not being tracked. Please call StartTracking() first."); } return(tracker); }
/// <summary> /// Creates a new instance of the <see cref="Camera"/> class from the specified <see cref="TrackObject"/> and <see cref="TriggerBounds"/>. /// </summary> /// <param name="trackObject">An <see cref="ITrackableObject"/> to follow.</param> /// <param name="triggerBounds">A <see cref="RectangleF"/> that represents how close to the edge of the screen an <see cref="ITrackableObject"/> must be to trigger panning.</param> public Camera(ITrackableObject trackObject, RectangleF triggerBounds) { if (trackObject == null || trackObject == this) { throw new ArgumentException($"The {nameof(trackObject)} must not be null or this instance."); } TrackObject = trackObject; TriggerBounds = triggerBounds; trackObject.TrackableObjectChanged += trackObject_TrackableObjectChanged; }
public void StartEdit(ITrackableObject editItem) { EditItem = (TItem)editItem; if (OnStartEdit != null) { OnStartEdit(Create, editItem); } StateHasChanged(); }
//public static void MergeTracking<TEntity>(this System.Collections.IEnumerable target, System.Collections.IEnumerable source) //{ // //Go through the new data and apply any modifications to the target. // foreach (ITrackableObject targetItem in target) // { // ITrackableObject sourceItem = null; // if (source != null) // sourceItem = source.FirstOrDefault(item => item.Id == targetItem.Id); // if (sourceItem != null) // { // targetItem.MergeTracking(sourceItem); // } // else // { // targetItem.StartTracking(); // } // } // //Go through the deleted items and apply them to the new data. // if (source != null) // { // foreach (ITrackableObject sourceItem in source.Where(item => item.IsDeleted())) // { // ITrackableObject targetItem = target.FirstOrDefault(item => item.Id == sourceItem.Id); // if (targetItem != null) // { // targetItem.Delete(); // } // } // } // ////Go through the added items and apply them to the new data. // //if (source != null) // //{ // // foreach (ITrackableObject sourceItem in source.Where(item => item.IsNew())) // // { // // target.Add((TEntity)sourceItem); // // } // //} // return target; //} public static TrackingState MergeTracking(this ITrackableObject target, ITrackableObject source) { TrackingState targetTracker = new TrackingState(target); TrackingState sourceTracker = GetTracker(source); foreach (var property in target.GetType().GetProperties()) { if (property.PropertyType != typeof(TrackingState) && ShouldAllowProperty(property)) { targetTracker.UnmodifiedState.Add(property, property.GetValue(target)); if (property.PropertyType.IsGenericType && property.PropertyType.IsAssignableTo(typeof(System.Collections.IEnumerable))) { dynamic targetList = property.GetValue(target); if (targetList != null) { dynamic sourceList = property.GetValue(source); MergeTracking(targetList, sourceList); } } else if (property.PropertyType.IsAssignableTo(typeof(ITrackableObject))) { ITrackableObject sourceItem = property.GetValue(source) as ITrackableObject; if (sourceItem != null) { if (sourceItem.IsNew() || sourceItem.IsDeleted()) { property.SetValue(target, sourceItem); } else { ITrackableObject trackedItem = property.GetValue(target) as ITrackableObject; if (trackedItem != null) { trackedItem.MergeTracking(sourceItem); } } } } else if (sourceTracker.UnmodifiedState.TryGetValue(property, out object sourceUnmodifiedValue)) { if (IsPropertyModified(source, property, sourceUnmodifiedValue)) { property.SetValue(target, property.GetValue(source)); } } } } trackedObjects[target] = targetTracker; return(targetTracker); }
public static void New(this ITrackableObject source, ITrackableObject parent = null) { var tracker = source.StartTracking(); if (parent != null) { var parentTracker = GetTracker(parent); foreach (var subscriber in parentTracker.OnChanged) { tracker.OnChanged.Add(subscriber); } } tracker.Added = true; }
public void ChangeProperties() { Item item = new Item() { Name = "abc" }.AsTrackable(); item.Name = "123"; ITrackableObject proxy = item.CastToTrackable(); Assert.True(proxy.IsChanged); Assert.Single(proxy.ChangedProperties); Assert.True(proxy.ChangedProperties.First().Name == nameof(Item.Name)); }
public static bool HasChanges(this ITrackableObject source) { TrackingState tracker = GetTracker(source); if (IsNew(source, tracker)) { return(true); } if (IsDeleted(source, tracker, null)) { return(true); } return(IsModified(source, tracker)); }
public static IList <TEntity> MergeTracking <TEntity>(this IList <TEntity> target, IList <TEntity> source) where TEntity : ITrackableObject { //Go through the new data and apply any modifications to the target. foreach (ITrackableObject targetItem in target) { ITrackableObject sourceItem = null; if (source != null) { sourceItem = source.FirstOrDefault(item => item.Id == targetItem.Id); } if (sourceItem != null) { targetItem.MergeTracking(sourceItem); } else { targetItem.StartTracking(); } } //Go through the deleted items and apply them to the new data. if (source != null) { foreach (ITrackableObject sourceItem in source.Where(item => item.IsDeleted())) { ITrackableObject targetItem = target.FirstOrDefault(item => item.Id == sourceItem.Id); if (targetItem != null) { targetItem.Delete(); } } } //Go through the added items and apply them to the new data. if (source != null) { foreach (ITrackableObject sourceItem in source.Where(item => item.IsNew())) { target.Add((TEntity)sourceItem); } } return(target); }
private static bool IsModified(ITrackableObject source, TrackingState tracker, bool includeAddDelete = false) { if (tracker.Added || tracker.Deleted) { return(includeAddDelete); } foreach (var property in tracker.UnmodifiedState) { if (property.Key.PropertyType.IsGenericType && property.Key.PropertyType.IsAssignableTo(typeof(System.Collections.IEnumerable))) { System.Collections.IEnumerable list = (System.Collections.IEnumerable)property.Value; foreach (object item in list) { ITrackableObject trackedItem = item as ITrackableObject; if (trackedItem != null) { if (IsModified(trackedItem, includeAddDelete)) { return(true); } } } } else if (property.Key.PropertyType.IsAssignableTo(typeof(ITrackableObject))) { ITrackableObject trackedItem = property.Key.GetValue(source) as ITrackableObject; if (trackedItem != null) { if (IsModified(trackedItem, includeAddDelete)) { return(true); } } } else { if (IsPropertyModified(source, property.Key, property.Value)) { return(true); } } } return(false); }
public void CancelEdit() { ITrackableObject trackedEditItem = (ITrackableObject)EditItem; if (trackedEditItem.IsTracking()) { trackedEditItem.Undo(); } EditItem = null; Create = false; JsRuntime.InvokeAsync <string>("closeModal", $"#trackedEditor_{EditorId}"); if (OnCancelEdit != null) { OnCancelEdit(Create, trackedEditItem); } }
private static bool IsPropertyModified(ITrackableObject source, PropertyInfo property, object referenceValue) { if (referenceValue == null) { if (property.GetValue(source) != null) { return(true); } } else { var propertyValue = property.GetValue(source); if (!referenceValue.Equals(propertyValue)) { return(true); } } return(false); }
public void SimplePropertyChange() { Item item = new Item(); item.Name = "old"; item = item.AsTrackable(); item.Name = "new"; ITrackableObject tracking = item.CastToTrackable(); Assert.NotNull(tracking); Assert.Single(tracking.ChangedProperties); SimplePropertyChange c = tracking.ChangedProperties.Cast <SimplePropertyChange>().First(); Assert.Equal(nameof(Item.Name), c.Name); Assert.Equal("old", c.OldValue); Assert.Equal("new", c.CurrentValue); }
public void CollectionChangesV2() { Item item = new Item(); item.Childs.Add(new Item() { Name = "Test" }); item = item.AsTrackable(); item.Childs.Add(new Item() { Name = "new" }); ITrackableObject trackableObject = item.CastToTrackable(); Assert.Equal(2, item.Childs.Count); Assert.Single(trackableObject.ChangedProperties); Assert.Single(trackableObject.ChangedProperties.Cast <CollectionPropertyChange>().First().Added); Assert.Empty(trackableObject.ChangedProperties.Cast <CollectionPropertyChange>().First().Removed); }
internal static void WhenChanged(ITrackableObject item, Action onChangedDelegate, TrackingCache cache) { if (onChangedDelegate == null) { throw new ArgumentNullException(nameof(onChangedDelegate)); } TrackingState tracker = GetTracker(item); tracker.OnChanged.Add(onChangedDelegate); PropertyInfo[] properties; if (!cache.Properties.TryGetValue(item.GetType(), out properties)) { properties = item.GetType().GetProperties(); cache.Properties[item.GetType()] = properties; } foreach (var property in properties) { if (property.PropertyType != typeof(TrackingState) && ShouldAllowProperty(property, cache)) { var value = property.GetValue(item); if (property.PropertyType.IsGenericType && property.PropertyType.IsAssignableTo(typeof(System.Collections.IEnumerable))) { System.Collections.IEnumerable list = (System.Collections.IEnumerable)value; foreach (object subItem in list) { ITrackableObject trackedItem = subItem as ITrackableObject; if (trackedItem != null) { WhenChanged(trackedItem, onChangedDelegate, cache); } } } } } }
/// <summary> /// Indicates that this item should be printed as part of a batch of entities. /// </summary> /// <param name="source">The entity item that needs to be printed.</param> public static void Print(this ITrackableObject source) { var tracker = GetTracker(source); tracker.Print = true; }
public static bool IsModified(this ITrackableObject source, bool includeAddDelete = false) { TrackingState tracker = GetTracker(source); return(IsModified(source, tracker, includeAddDelete)); }
public static void Delete(this ITrackableObject source) { TrackingState tracker = GetTracker(source); tracker.Deleted = true; }
public static bool IsTracking(this ITrackableObject source) { return(trackedObjects.ContainsKey(source)); }
public static bool IsDeleted(this ITrackableObject source) { TrackingState tracker = GetTracker(source); return(IsDeleted(source, tracker, null)); }
/// <summary> /// Determines if the current <see cref="Camera"/> instances contains the <see cref="ITrackableObject"/>. /// </summary> /// <param name="testObject">The <see cref="ITrackableObject"/> to test.</param> /// <param name="entirelyContained">If true, will only return true if the testObject is entirely contained in the <see cref="Camera.Bounds"/>, otherwise will return true if any part of the testObject is contained.</param> /// <returns>If entirelyContained is true, returns true only if the entire testObject is contained within <see cref="Camera.Bounds"/>. If entirelyContained is false, returns true if any part of the testObject is contained within <see cref="Camera.Bounds"/>.</returns> public bool Contains(ITrackableObject testObject, bool entirelyContained) { if (entirelyContained) { return Bounds.Contains(new RectangleF(testObject.Position, testObject.Size)); } else { // We're only checking corner cases as we are assuming that the `testObject` is not *bigger* than the `Camera`. If it is, then that's a different issue. (We'll likely fix this in the future, just not today!) if (Bounds.Contains(testObject.Position)) { return true; } if (Bounds.Contains(testObject.Position.X, testObject.Size.Height)) { return true; } if (Bounds.Contains(testObject.Size.Width, testObject.Position.Y)) { return true; } if (Bounds.Contains(testObject.Size.Width, testObject.Size.Height)) { return true; } } return false; }
/// <summary> /// Clear the print flag from the item. /// </summary> /// <param name="source">The tracked item to clear the print flag on.</param> public static void ClearPrint(this ITrackableObject source) { var tracker = GetTracker(source); tracker.Print = false; }
public static bool IsNew(this ITrackableObject source) { TrackingState tracker = GetTracker(source); return(IsNew(source, tracker)); }
/// <summary> /// Determines whether this entity requires printing. /// </summary> /// <param name="source">The source.</param> /// <returns> /// <c>true</c> if the specified source has print; otherwise, <c>false</c>. /// </returns> public static bool IsPrintRequired(this ITrackableObject source) { TrackingState tracker = GetTracker(source); return(tracker.Print); }
private static TrackingState StartTracking(ITrackableObject source, TrackingCache cache) { TrackingState tracker = new TrackingState(source); PropertyInfo[] properties; if (!cache.Properties.TryGetValue(source.GetType(), out properties)) { properties = source.GetType().GetProperties(); cache.Properties[source.GetType()] = properties; } foreach (var property in properties) { if (property.PropertyType != typeof(TrackingState) && ShouldAllowProperty(property, cache)) { var value = property.GetValue(source); if (property.PropertyType.IsGenericType && property.PropertyType.IsAssignableTo(typeof(System.Collections.IEnumerable))) { System.Collections.IEnumerable list = (System.Collections.IEnumerable)value; List <ITrackableObject> deletedItems = new List <ITrackableObject>(); foreach (object item in list) { ITrackableObject trackedItem = item as ITrackableObject; if (trackedItem != null) { if (trackedItem.IsTracking() && trackedItem.IsDeleted()) { deletedItems.Add(trackedItem); StopTracking(trackedItem); } else { StartTracking(trackedItem, cache); } } } //Remove any items we detected as having been deleted. IList editableList = list as IList; if (editableList != null) { foreach (var removeItem in deletedItems) { editableList.Remove(removeItem); } } } else if (property.PropertyType.IsAssignableTo(typeof(ITrackableObject))) { ITrackableObject trackedItem = value as ITrackableObject; if (trackedItem != null) { StartTracking(trackedItem, cache); } } tracker.UnmodifiedState.Add(property, value); } } trackedObjects[source] = tracker; return(tracker); }
/// <summary> /// Creates a new instance of the <see cref="Camera"/> class from the specified <see cref="TrackObject"/> and <see cref="TriggerBounds"/>. /// </summary> /// <param name="trackObject">An <see cref="ITrackableObject"/> to follow.</param> /// <param name="triggerBounds">A <see cref="RectangleF"/> that represents how close to the edge of the screen an <see cref="ITrackableObject"/> must be to trigger panning.</param> public Camera(ITrackableObject trackObject, RectangleF triggerBounds) { if (trackObject == null || trackObject == this) { throw new ArgumentException($"The {nameof(trackObject)} must not be null or this instance."); } TrackObject = trackObject; TriggerBounds = triggerBounds; trackObject.TrackableObjectChanged += trackObject_TrackableObjectChanged; }
public static void WhenChanged(this ITrackableObject item, Action onChangedDelegate) { TrackingCache cache = new TrackingCache(); WhenChanged(item, onChangedDelegate, cache); }