/// <summary> /// Raises the <see cref="Changed"/> event with the given parameters. /// </summary> /// <param name="index">The index where the change occurred, if applicable. <c>null</c> otherwise.</param> /// <param name="changeType">The type of change that occurred.</param> /// <param name="oldValue">The old value of this content.</param> /// <param name="newValue">The new value of this content.</param> protected void NotifyContentChanged(object index, ContentChangeType changeType, object oldValue, object newValue) { var args = new ContentChangeEventArgs(this, index, changeType, oldValue, newValue); Changed?.Invoke(this, args); FinalizeChange?.Invoke(this, args); }
/// <inheritdoc/> public override void Add(object newItem) { var collectionDescriptor = Descriptor as CollectionDescriptor; if (collectionDescriptor != null) { // Some collection (such as sets) won't add item at the end but at an arbitrary location. // Better send a null index in this case than sending a wrong value. var value = Value; var index = collectionDescriptor.IsList ? new Index(collectionDescriptor.GetCollectionCount(value)) : Index.Empty; var args = new ContentChangeEventArgs(this, index, ContentChangeType.CollectionAdd, null, newItem); NotifyContentChanging(args); collectionDescriptor.Add(value, newItem); if (value.GetType().GetTypeInfo().IsValueType) { var containerValue = Container.Value; Member.Set(containerValue, value); } UpdateReferences(); NotifyContentChanged(args); } else { throw new NotSupportedException("Unable to set the node value, the collection is unsupported"); } }
public AssetContentChangeEventArgs(ContentChangeEventArgs e, OverrideType previousOverride, OverrideType newOverride, ItemId itemId) : base(e.Content, e.Index, e.ChangeType, e.OldValue, e.NewValue) { PreviousOverride = previousOverride; NewOverride = newOverride; ItemId = itemId; }
/// <summary> /// Raises the <see cref="Changing"/> event with the given parameters. /// </summary> /// <param name="index">The index where the change occurred, if applicable. <c>null</c> otherwise.</param> /// <param name="changeType">The type of change that occurred.</param> /// <param name="oldValue">The old value of this content.</param> /// <param name="newValue">The new value of this content.</param> protected void NotifyContentChanging(Index index, ContentChangeType changeType, object oldValue, object newValue) { var args = new ContentChangeEventArgs(this, index, changeType, oldValue, newValue); PrepareChange?.Invoke(this, args); Changing?.Invoke(this, args); }
private void ContentPrepareChange(object sender, ContentChangeEventArgs e) { var node = e.Content.OwnerNode as IGraphNode; if (node != null) { foreach (var child in node.GetAllChildNodes()) { UnregisterNode(child); } } PrepareChange?.Invoke(sender, e); }
private void ContentChanged(object sender, ContentChangeEventArgs e) { var node = e.Content.OwnerNode as IGraphNode; if (node != null) { foreach (var child in GetAllChildNodes(node)) { child.Content.Changing += ContentChanging; child.Content.Changed += ContentChanged; } } Changed?.Invoke(sender, e); }
private void Update(object newValue, Index index, bool sendNotification) { var oldValue = Retrieve(index); ContentChangeEventArgs args = null; if (sendNotification) { args = new ContentChangeEventArgs(this, index, ContentChangeType.ValueChange, oldValue, newValue); NotifyContentChanging(args); } if (!index.IsEmpty) { var collectionDescriptor = Descriptor as CollectionDescriptor; var dictionaryDescriptor = Descriptor as DictionaryDescriptor; if (collectionDescriptor != null) { collectionDescriptor.SetValue(Value, index.Int, newValue); } else if (dictionaryDescriptor != null) { dictionaryDescriptor.SetValue(Value, index.Value, newValue); } else { throw new NotSupportedException("Unable to set the node value, the collection is unsupported"); } } else { if (Container.Value == null) { throw new InvalidOperationException("Container's value is null"); } var containerValue = Container.Value; Member.Set(containerValue, newValue); if (Container.Value.GetType().GetTypeInfo().IsValueType) { Container.UpdateFromMember(containerValue, Index.Empty); } } UpdateReferences(); if (sendNotification) { NotifyContentChanged(args); } }
/// <inheritdoc/> public override void Add(object newItem, Index itemIndex) { var collectionDescriptor = Descriptor as CollectionDescriptor; var dictionaryDescriptor = Descriptor as DictionaryDescriptor; if (collectionDescriptor != null) { var index = collectionDescriptor.IsList ? itemIndex : Index.Empty; var value = Value; var args = new ContentChangeEventArgs(this, index, ContentChangeType.CollectionAdd, null, newItem); NotifyContentChanging(args); if (collectionDescriptor.GetCollectionCount(value) == itemIndex.Int || !collectionDescriptor.HasInsert) { collectionDescriptor.Add(value, newItem); } else { collectionDescriptor.Insert(value, itemIndex.Int, newItem); } if (value.GetType().GetTypeInfo().IsValueType) { var containerValue = Container.Value; Member.Set(containerValue, value); } UpdateReferences(); NotifyContentChanged(args); } else if (dictionaryDescriptor != null) { var args = new ContentChangeEventArgs(this, itemIndex, ContentChangeType.CollectionAdd, null, newItem); NotifyContentChanging(args); var value = Value; dictionaryDescriptor.AddToDictionary(value, itemIndex.Value, newItem); if (value.GetType().GetTypeInfo().IsValueType) { var containerValue = Container.Value; Member.Set(containerValue, value); } UpdateReferences(); NotifyContentChanged(args); } else { throw new NotSupportedException("Unable to set the node value, the collection is unsupported"); } }
/// <inheritdoc/> public override void Add(object newItem, Index itemIndex) { var collectionDescriptor = Descriptor as CollectionDescriptor; var dictionaryDescriptor = Descriptor as DictionaryDescriptor; if (collectionDescriptor != null) { var index = collectionDescriptor.IsList ? itemIndex : Index.Empty; var value = Value; var args = new ContentChangeEventArgs(this, index, ContentChangeType.CollectionAdd, null, newItem); NotifyContentChanging(args); if (collectionDescriptor.GetCollectionCount(value) == itemIndex.Int || !collectionDescriptor.HasInsert) { collectionDescriptor.Add(value, newItem); } else { collectionDescriptor.Insert(value, itemIndex.Int, newItem); } if (value.GetType().GetTypeInfo().IsValueType) { var containerValue = Container.Value; Member.Set(containerValue, value); } UpdateReferences(); NotifyContentChanged(args); } else if (dictionaryDescriptor != null) { var args = new ContentChangeEventArgs(this, itemIndex, ContentChangeType.CollectionAdd, null, newItem); NotifyContentChanging(args); var value = Value; dictionaryDescriptor.AddToDictionary(value, itemIndex.Value, newItem); if (value.GetType().GetTypeInfo().IsValueType) { var containerValue = Container.Value; Member.Set(containerValue, value); } UpdateReferences(); NotifyContentChanged(args); } else throw new NotSupportedException("Unable to set the node value, the collection is unsupported"); }
/// <inheritdoc/> public override void Remove(object item, Index itemIndex) { if (itemIndex.IsEmpty) { throw new ArgumentException(@"The given index should not be empty.", nameof(itemIndex)); } var args = new ContentChangeEventArgs(this, itemIndex, ContentChangeType.CollectionRemove, item, null); NotifyContentChanging(args); var collectionDescriptor = Descriptor as CollectionDescriptor; var dictionaryDescriptor = Descriptor as DictionaryDescriptor; var value = Value; if (collectionDescriptor != null) { if (collectionDescriptor.HasRemoveAt) { collectionDescriptor.RemoveAt(value, itemIndex.Int); } else { collectionDescriptor.Remove(value, item); } } else if (dictionaryDescriptor != null) { dictionaryDescriptor.Remove(value, itemIndex.Value); } else { throw new NotSupportedException("Unable to set the node value, the collection is unsupported"); } if (value.GetType().GetTypeInfo().IsValueType) { var containerValue = Container.Value; Member.Set(containerValue, value); } UpdateReferences(); NotifyContentChanged(args); }
/// <inheritdoc/> public override void Add(object newItem) { var collectionDescriptor = Descriptor as CollectionDescriptor; if (collectionDescriptor != null) { // Some collection (such as sets) won't add item at the end but at an arbitrary location. // Better send a null index in this case than sending a wrong value. var value = Value; var index = collectionDescriptor.IsList ? new Index(collectionDescriptor.GetCollectionCount(value)) : Index.Empty; var args = new ContentChangeEventArgs(this, index, ContentChangeType.CollectionAdd, null, newItem); NotifyContentChanging(args); collectionDescriptor.Add(value, newItem); if (value.GetType().GetTypeInfo().IsValueType) { var containerValue = Container.Value; Member.Set(containerValue, value); } UpdateReferences(); NotifyContentChanged(args); } else throw new NotSupportedException("Unable to set the node value, the collection is unsupported"); }
/// <summary> /// Raises the <see cref="Changing"/> event with the given parameters. /// </summary> /// <param name="args">The arguments of the event.</param> protected void NotifyContentChanging(ContentChangeEventArgs args) { PrepareChange?.Invoke(this, args); Changing?.Invoke(this, args); }
private void Update(object newValue, Index index, bool sendNotification) { var oldValue = Retrieve(index); ContentChangeEventArgs args = null; if (sendNotification) { args = new ContentChangeEventArgs(this, index, ContentChangeType.ValueChange, oldValue, newValue); NotifyContentChanging(args); } if (!index.IsEmpty) { var collectionDescriptor = Descriptor as CollectionDescriptor; var dictionaryDescriptor = Descriptor as DictionaryDescriptor; if (collectionDescriptor != null) { collectionDescriptor.SetValue(Value, index.Int, newValue); } else if (dictionaryDescriptor != null) { dictionaryDescriptor.SetValue(Value, index.Value, newValue); } else throw new NotSupportedException("Unable to set the node value, the collection is unsupported"); } else { if (Container.Value == null) throw new InvalidOperationException("Container's value is null"); var containerValue = Container.Value; Member.Set(containerValue, newValue); if (Container.Value.GetType().GetTypeInfo().IsValueType) Container.UpdateFromMember(containerValue, Index.Empty); } UpdateReferences(); if (sendNotification) { NotifyContentChanged(args); } }
private void ContentChanged(object sender, ContentChangeEventArgs e) { var path = GetPath(e.Content.OwnerNode); Changed?.Invoke(sender, new GraphContentChangeEventArgs(e, path)); }
private void ContentPrepareChange(object sender, ContentChangeEventArgs e) { var node = e.Content.OwnerNode as IGraphNode; var path = GetPath(e.Content.OwnerNode); if (node != null) { var visitor = new GraphVisitorBase(); visitor.Visiting += UnregisterNode; switch (e.ChangeType) { case ContentChangeType.ValueChange: // The changed node itself is still valid, we don't want to unregister it visitor.SkipRootNode = true; visitor.Visit(node, path); break; case ContentChangeType.CollectionRemove: if (node.Content.IsReference && e.OldValue != null) { var removedNode = node.Content.Reference.AsEnumerable[e.Index].TargetNode; var removedNodePath = path?.PushIndex(e.Index); if (removedNode != null) { visitor.Visit(removedNode, removedNodePath); } } break; } } PrepareChange?.Invoke(sender, new GraphContentChangeEventArgs(e, path)); }
private void ContentFinalizeChange(object sender, ContentChangeEventArgs e) { var node = e.Content.OwnerNode as IGraphNode; var path = GetPath(e.Content.OwnerNode); if (node != null) { var visitor = new GraphVisitorBase(); visitor.Visiting += RegisterNode; switch (e.ChangeType) { case ContentChangeType.ValueChange: // The changed node itself is still valid, we don't want to re-register it visitor.SkipRootNode = true; visitor.Visit(node, path); break; case ContentChangeType.CollectionAdd: if (node.Content.IsReference && e.NewValue != null) { var index = e.Index; IGraphNode addedNode; if (!index.IsEmpty) { addedNode = node.Content.Reference.AsEnumerable[e.Index].TargetNode; } else { var reference = node.Content.Reference.AsEnumerable.First(x => x.TargetNode.Content.Retrieve() == e.NewValue); index = reference.Index; addedNode = reference.TargetNode; } if (addedNode != null) { var addedNodePath = path?.PushIndex(index); visitor.Visit(addedNode, addedNodePath); } } break; } } FinalizeChange?.Invoke(sender, new GraphContentChangeEventArgs(e, path)); }
private void ContentChanged(object sender, ContentChangeEventArgs e) { Changed?.Invoke(sender, new GraphContentChangeEventArgs(e)); }
/// <inheritdoc/> public override void Remove(object item, Index itemIndex) { if (itemIndex.IsEmpty) throw new ArgumentException(@"The given index should not be empty.", nameof(itemIndex)); var args = new ContentChangeEventArgs(this, itemIndex, ContentChangeType.CollectionRemove, item, null); NotifyContentChanging(args); var collectionDescriptor = Descriptor as CollectionDescriptor; var dictionaryDescriptor = Descriptor as DictionaryDescriptor; var value = Value; if (collectionDescriptor != null) { if (collectionDescriptor.HasRemoveAt) { collectionDescriptor.RemoveAt(value, itemIndex.Int); } else { collectionDescriptor.Remove(value, item); } } else if (dictionaryDescriptor != null) { dictionaryDescriptor.Remove(value, itemIndex.Value); } else throw new NotSupportedException("Unable to set the node value, the collection is unsupported"); if (value.GetType().GetTypeInfo().IsValueType) { var containerValue = Container.Value; Member.Set(containerValue, value); } UpdateReferences(); NotifyContentChanged(args); }
/// <summary> /// Raises the <see cref="Changed"/> event with the given arguments. /// </summary> /// <param name="args">The arguments of the event.</param> protected void NotifyContentChanged(ContentChangeEventArgs args) { Changed?.Invoke(this, args); FinalizeChange?.Invoke(this, args); }
/// <summary> /// Raises the <see cref="Changed"/> event with the given parameters. /// </summary> /// <param name="index">The index where the change occurred, if applicable. <c>null</c> otherwise.</param> /// <param name="oldValue">The old value of this content.</param> /// <param name="newValue">The new value of this content.</param> protected void NotifyContentChanged(object index, object oldValue, object newValue) { var args = new ContentChangeEventArgs(this, index, oldValue, newValue); Changed?.Invoke(this, args); FinalizeChange?.Invoke(this, args); }
/// <summary> /// Raises the <see cref="Changing"/> event with the given parameters. /// </summary> /// <param name="index">The index where the change occurred, if applicable. <c>null</c> otherwise.</param> /// <param name="oldValue">The old value of this content.</param> /// <param name="newValue">The new value of this content.</param> protected void NotifyContentChanging(object index, object oldValue, object newValue) { var args = new ContentChangeEventArgs(this, index, oldValue, newValue); PrepareChange?.Invoke(this, args); Changing?.Invoke(this, args); }
private void ContentChanged(object sender, ContentChangeEventArgs e) { Changed?.Invoke(sender, e); }
private void ContentChanged(object sender, ContentChangeEventArgs e) { // Make sure that we have item ids everywhere we're supposed to. AssetCollectionItemIdHelper.GenerateMissingItemIds(e.Content.Retrieve()); var node = (AssetNode)e.Content.OwnerNode; if (node.IsNonIdentifiableCollectionContent) return; // Create new ids for collection items var baseNode = (AssetNode)BaseContent?.OwnerNode; var isOverriding = !baseNode?.contentUpdating == true; var removedId = ItemId.Empty; switch (e.ChangeType) { case ContentChangeType.ValueChange: break; case ContentChangeType.CollectionAdd: { var collectionDescriptor = e.Content.Descriptor as CollectionDescriptor; var itemIds = CollectionItemIdHelper.GetCollectionItemIds(e.Content.Retrieve()); // Compute the id we will add for this item ItemId itemId; if (baseNode?.contentUpdating == true) { var baseCollection = baseNode.Content.Retrieve(); var baseIds = CollectionItemIdHelper.GetCollectionItemIds(baseCollection); itemId = itemIds.FindMissingId(baseIds); } else { itemId = restoringId != ItemId.Empty ? restoringId : ItemId.New(); } // Add the id to the proper location (insert or add) if (collectionDescriptor != null) { if (e.Index != Index.Empty) { itemIds.Insert(e.Index.Int, itemId); } else { throw new InvalidOperationException("An item has been added to a collection that does not have a predictable Add. Consider using NonIdentifiableCollectionItemsAttribute on this collection."); } } else { itemIds[e.Index.Value] = itemId; } } break; case ContentChangeType.CollectionRemove: { var collectionDescriptor = e.Content.Descriptor as CollectionDescriptor; if (collectionDescriptor != null) { var itemIds = CollectionItemIdHelper.GetCollectionItemIds(e.Content.Retrieve()); removedId = itemIds.DeleteAndShift(e.Index.Int, isOverriding); } else { var itemIds = CollectionItemIdHelper.GetCollectionItemIds(e.Content.Retrieve()); removedId = itemIds.Delete(e.Index.Value, isOverriding); } } break; default: throw new ArgumentOutOfRangeException(); } // Don't update override if propagation from base is disabled. if (PropertyGraph?.Container?.PropagateChangesFromBase == false) return; // Mark it as New if it does not come from the base if (!baseNode?.contentUpdating == true && !ResettingOverride) { if (e.ChangeType != ContentChangeType.CollectionRemove) { if (e.Index == Index.Empty) { OverrideContent(!ResettingOverride); } else { OverrideItem(!ResettingOverride, e.Index); } } else { OverrideDeletedItem(true, removedId); } } }
private void AssetContentChanged(object sender, ContentChangeEventArgs e) { var previousOverride = previousOverrides[e.Content.OwnerNode]; previousOverrides.Remove(e.Content.OwnerNode); var itemId = ItemId.Empty; var overrideValue = OverrideType.Base; var node = (AssetNode)e.Content.OwnerNode; if (e.ChangeType == ContentChangeType.ValueChange || e.ChangeType == ContentChangeType.CollectionAdd) { if (e.Index == Index.Empty) { // No index, we're changing an object that is not in a collection, let's just retrieve it's override status. overrideValue = node.GetContentOverride(); } else { // We're changing an item of a collection. If the collection has identifiable items, retrieve the override status of the item. if (!node.IsNonIdentifiableCollectionContent) { overrideValue = node.GetItemOverride(e.Index); } // Also retrieve the id of the modified item (this should fail only if the collection doesn't have identifiable items) CollectionItemIdentifiers ids; if (CollectionItemIdHelper.TryGetCollectionItemIds(e.Content.Retrieve(), out ids)) { ids.TryGet(e.Index.Value, out itemId); } } } else { // When deleting we are always overriding (unless there is no base) overrideValue = !((AssetNode)node.BaseContent?.OwnerNode)?.contentUpdating == true ? OverrideType.New : OverrideType.Base; itemId = removedItemIds[e.Content.OwnerNode]; removedItemIds.Remove(e.Content.OwnerNode); } Changed?.Invoke(sender, new AssetContentChangeEventArgs(e, previousOverride, overrideValue, itemId)); }
private void OnBaseContentChanged(ContentChangeEventArgs e, IContent assetContent) { // Ignore base change if propagation is disabled. if (!Container.PropagateChangesFromBase) return; UpdatingPropertyFromBase = true; // TODO: we want to refresh the base only starting from the modified node! RefreshBase(baseGraph); var rootNode = (AssetNode)assetContent.OwnerNode; var visitor = CreateReconcilierVisitor(); visitor.Visiting += (node, path) => ReconcileWithBaseNode((AssetNode)node); visitor.Visit(rootNode); UpdatingPropertyFromBase = false; BaseContentChanged?.Invoke(e, assetContent); }
private void ContentChanged(object sender, ContentChangeEventArgs e) { if (!updatingValue) OnPropertyChanged(nameof(VirtualObservableNode<object>.TypedValue)); }
private void AssetContentChanging(object sender, ContentChangeEventArgs e) { var overrideValue = OverrideType.Base; var node = (AssetNode)e.Content.OwnerNode; if (e.ChangeType == ContentChangeType.ValueChange || e.ChangeType == ContentChangeType.CollectionRemove) { // For value change and remove, we store the current override state. if (e.Index == Index.Empty) { overrideValue = node.GetContentOverride(); } else if (!node.IsNonIdentifiableCollectionContent) { overrideValue = node.GetItemOverride(e.Index); } } if (e.ChangeType == ContentChangeType.CollectionRemove) { // For remove, we also collect the id of the item that will be removed, so we can pass it to the Changed event. var itemId = ItemId.Empty; CollectionItemIdentifiers ids; if (CollectionItemIdHelper.TryGetCollectionItemIds(e.Content.Retrieve(), out ids)) { ids.TryGet(e.Index.Value, out itemId); } removedItemIds[e.Content.OwnerNode] = itemId; } if (e.ChangeType == ContentChangeType.CollectionAdd && !node.IsNonIdentifiableCollectionContent) { // If the change is an add, we set the previous override as New so the Undo will try to remove the item instead of resetting to the base value previousOverrides[e.Content.OwnerNode] = OverrideType.New; } previousOverrides[e.Content.OwnerNode] = overrideValue; }