4 using System.Collections.Generic;
7 using SiliconStudio.Core.Reflection;
8 using SiliconStudio.Quantum;
9 using SiliconStudio.Quantum.Contents;
10 using SiliconStudio.Quantum.References;
12 namespace SiliconStudio.Presentation.Quantum
16 private readonly
bool isPrimitive;
20 private bool isInitialized;
32 : base(ownerViewModel, baseName, parentNode, index)
34 if (modelNode == null)
throw new ArgumentNullException(
"modelNode");
35 if (baseName == null && index == null)
36 throw new ArgumentException(
"baseName and index can't be both null.");
38 this.isPrimitive = isPrimitive;
39 sourceNode = modelNode;
41 CombineMode = index != null && isPrimitive ? CombineMode.AlwaysCombine : CombineMode.CombineOnlyForAll;
42 targetNode = GetTargetNode(modelNode, index);
62 internal void Initialize()
67 private void Initialize(
bool isUpdating)
69 var path = ModelNodePath.GetPath(((ObservableModelNode)Root).sourceNode, targetNode);
71 throw new InvalidOperationException(
"Unable to retrieve the path of the given model node.");
73 foreach (var command
in targetNode.Commands)
75 var commandWrapper =
new ModelNodeCommandWrapper(ServiceProvider, command, Path, Owner.Identifier, path, Owner.ModelContainer, Owner.GetDirtiableViewModels(
this));
76 AddCommand(commandWrapper);
80 GenerateChildren(targetNode, isUpdating);
84 if (Owner.ObservableViewModelService != null)
86 var data = Owner.ObservableViewModelService.RequestAssociatedData(
this, isUpdating);
87 SetValue(ref associatedData, data,
"AssociatedData");
90 CheckDynamicMemberConsistency();
97 public sealed
override bool IsPrimitive {
get { AssertInit();
return isPrimitive; } }
102 public sealed
override bool HasList {
get { AssertInit();
return (targetNode.Content.Descriptor is
CollectionDescriptor && (Parent == null || (ModelNodeParent != null && ModelNodeParent.targetNode.Content.Value != targetNode.Content.Value))) || targetNode.Content.Reference is
ReferenceEnumerable; } }
107 public sealed
override bool HasDictionary {
get { AssertInit();
return (targetNode.Content.Descriptor is
DictionaryDescriptor && (Parent == null || (ModelNodeParent != null && ModelNodeParent.targetNode.Content.Value != targetNode.Content.Value))) || (targetNode.Content.Reference is
ReferenceEnumerable && ((
ReferenceEnumerable)targetNode.Content.Reference).IsDictionary); } }
112 internal Guid ModelGuid {
get {
return targetNode.Guid; } }
114 private ObservableModelNode ModelNodeParent {
get { AssertInit();
for (var p = Parent; p != null; p = p.Parent) { var mp = p as ObservableModelNode;
if (mp != null)
return mp; }
return null; } }
132 return sourceNode == node;
138 return memberContent != null ? memberContent.Member : null;
141 internal void CheckConsistency()
144 if (sourceNode != targetNode)
148 if (objectReference != null && targetNode != objectReference.TargetNode)
152 if (referenceEnumerable != null && Index != null)
154 if (!referenceEnumerable.ContainsIndex(Index))
155 throw new ObservableViewModelConsistencyException(
this,
"The Index of this node does not exist in the reference of its source node.");
157 if (targetNode != referenceEnumerable[Index].TargetNode)
159 throw new ObservableViewModelConsistencyException(
this,
"The target node does not match the target of the source node object reference.");
164 var modelContentValue = GetModelContentValue();
165 if (!Equals(modelContentValue, Value))
171 foreach (var child
in Children.OfType<ObservableModelNode>())
173 if (targetNode.Content.IsReference)
175 var objectReference = targetNode.Content.Reference as ObjectReference;
176 if (objectReference != null)
178 throw new ObservableViewModelConsistencyException(
this,
"The target node does not match the target of the source node object reference.");
181 else if (!targetNode.Children.Contains(child.sourceNode))
183 if (child.Index == null || !child.IsPrimitive)
185 throw new ObservableViewModelConsistencyException(child,
"The source node of this node is not a child of the target node of its parent.");
188 child.CheckConsistency();
195 base.ClearCommands();
202 throw new InvalidOperationException(
"Accessing a property of a non-initialized ObservableNode.");
215 if (Index != null && dictionary != null)
216 return dictionary.GetValue(sourceNode.Content.Value, Index);
218 if (Index != null && list != null)
219 return list.GetValue(sourceNode.Content.Value, Index);
221 return sourceNode.Content.Value;
233 if (Index != null && dictionary != null)
235 if (!Equals(dictionary.GetValue(sourceNode.Content.Value, Index), newValue))
238 dictionary.SetValue(sourceNode.Content.Value, Index, newValue);
241 else if (Index != null && list != null)
243 if (!Equals(list.GetValue(sourceNode.Content.Value, Index), newValue))
246 list.SetValue(sourceNode.Content.Value, Index, newValue);
251 if (!Equals(sourceNode.Content.Value, newValue))
254 sourceNode.Content.Value = newValue;
260 Owner.ModelContainer.UpdateReferences(sourceNode);
266 private void GenerateChildren(
IModelNode modelNode,
bool isUpdating)
270 var referenceEnumerable = modelNode.Content.Reference as ReferenceEnumerable;
271 if (referenceEnumerable != null)
273 foreach (var reference
in referenceEnumerable)
278 var type = reference.TargetNode != null && reference.TargetNode.Content.IsPrimitive ? reference.TargetNode.Content.Type : reference.Type;
279 var observableNode = Create(Owner, null,
false,
this, modelNode, type, reference.Index);
280 observableNode.Initialize(isUpdating);
281 AddChild(observableNode);
286 var targetViewModelNode = ((ObjectReference)modelNode.
Content.
Reference).TargetNode;
287 GenerateChildren(targetViewModelNode, isUpdating);
294 if (dictionary != null && modelNode.
Content.
Value != null)
297 foreach (var key
in dictionary.GetKeys(modelNode.
Content.
Value))
299 var observableChild =
Create(Owner, null,
true,
this, modelNode, dictionary.ValueType, key);
300 observableChild.Initialize(isUpdating);
301 AddChild(observableChild);
304 else if (list != null && modelNode.
Content.
Value != null)
307 for (
int i = 0; i < list.GetCollectionCount(modelNode.Content.Value); ++i)
309 var observableChild =
Create(Owner, null,
true,
this, modelNode, list.ElementType, i);
310 observableChild.Initialize(isUpdating);
311 AddChild(observableChild);
317 foreach (var child
in modelNode.
Children)
319 var observableChild =
Create(Owner, child.Name, child.Content.IsPrimitive,
this, child, child.Content.Type, null);
320 observableChild.Initialize(isUpdating);
321 AddChild(observableChild);
327 internal void Refresh()
329 if (Parent == null)
throw new InvalidOperationException(
"The node to refresh can't be a root node.");
331 OnPropertyChanging(
"IsPrimitive",
"HasList",
"HasDictionary");
333 targetNode = GetTargetNode(sourceNode, Index);
337 foreach (var child
in Children.ToList())
342 OnPropertyChanged(
"IsPrimitive",
"HasList",
"HasDictionary");
347 var objectReference = sourceNode.Content.Reference as ObjectReference;
348 var referenceEnumerable = sourceNode.Content.Reference as ReferenceEnumerable;
349 if (objectReference != null)
351 return objectReference.TargetNode;
353 if (referenceEnumerable != null && index != null)
355 return referenceEnumerable[index].TargetNode;
373 : base(ownerViewModel, baseName, isPrimitive, parentNode, modelNode, index)
375 DependentProperties.Add(Tuple.Create(
"TypedValue",
"Value"));
386 return (T)GetModelContentValue();
391 var previousValue = (T)GetModelContentValue();
392 bool hasChanged = !Equals(previousValue, value);
395 OnPropertyChanging(
"TypedValue");
399 SetModelContentValue(value);
403 OnPropertyChanged(
"TypedValue");
404 string displayName = Owner.FormatSingleUpdateMessage(
this, value);
405 var dirtiables = Owner.GetDirtiableViewModels(
this);
406 var nodePath = GetModelNodePath();
408 var checkNode = nodePath.GetNode();
409 if (!MatchNode(checkNode))
410 throw new InvalidOperationException(
"An internal error occured while building the node path.");
412 Owner.RegisterAction(displayName, nodePath, Path, Index, dirtiables, value, previousValue);
418 public override Type Type {
get {
return typeof(T); } }
421 public override sealed
object Value {
get {
return TypedValue; } set { TypedValue = (T)value; } }
Provides a descriptor for a System.Collections.ICollection.
IReference Reference
Gets or sets the reference hold by this content, if applicable.
ObservableModelNode(ObservableViewModel ownerViewModel, string baseName, bool isPrimitive, SingleObservableNode parentNode, IModelNode modelNode, object index)
Construct a new ObservableModelNode.
IMemberDescriptor GetMemberDescriptor()
ObservableModelNode(ObservableViewModel ownerViewModel, string baseName, bool isPrimitive, SingleObservableNode parentNode, IModelNode modelNode, object index=null)
Initializes a new instance of the ObservableModelNode class.
object GetModelContentValue()
Retrieve the value of the model content associated to this ObservableModelNode.
Describe a member of an object.
IContent Content
Gets the content of the IModelNode.
A class representing an enumeration of references to multiple objects.
bool SetModelContentValue(object newValue)
Sets the value of the model content associated to this ObservableModelNode. The value is actually mod...
Provides a descriptor for a System.Collections.IDictionary.
An implementation of IContent that gives access to a member of an object.
CombineMode
An enum that describes what to do with a node or a command when combining view models.
bool MatchNode(IModelNode node)
Indicates whether this ObservableModelNode instance corresponds to the given IModelNode.
Creates a new file, always. If a file exists, the function overwrites the file, clears the existing a...
bool IsReference
Gets wheither this content holds a reference or is a direct value.
ModelNodePath GetModelNodePath()
Retrieves a ModelNodePath object corresponding to the path of the model node contained in this Observ...
A class representing a reference to another object that has a different model.
The IModelNode interface represents a node in a model object. A model object is represented by a grap...
object Value
Gets or sets the value.
IReadOnlyCollection< IModelNode > Children
Gets the children collection.
A class describing the path of a node, relative to a root node. The path can cross references...
An exception that occurs during consistency checks of ObservableViewModel nodes, indicating that an O...