4 using System.Collections.Generic;
5 using System.Diagnostics.Contracts;
8 using SiliconStudio.Presentation.Services;
9 using SiliconStudio.Presentation.ViewModel;
10 using SiliconStudio.Quantum;
12 namespace SiliconStudio.Presentation.Quantum
16 public const string DefaultLoggerName =
"Quantum";
17 public const string HasChildPrefix =
"HasChild_";
18 public const string HasCommandPrefix =
"HasCommand_";
19 public const string HasAssociatedDataPrefix =
"HasAssociatedData_";
24 private bool singleNodeActionRegistered;
26 private Func<SingleObservableNode, object, string> formatSingleUpdateMessage = (node, value) =>
string.Format(
"Update '{0}'", node.Name);
27 private Func<CombinedObservableNode, object, string> formatCombinedUpdateMessage = (node, value) =>
string.Format(
"Update '{0}'", node.Name);
29 private readonly Dictionary<ObservableModelNode, List<IDirtiableViewModel>> dirtiableViewModels =
new Dictionary<ObservableModelNode, List<IDirtiableViewModel>>();
37 : base(serviceProvider)
39 if (modelContainer == null)
throw new ArgumentNullException(
"modelContainer");
40 this.modelContainer = modelContainer;
52 : this(serviceProvider, modelContainer)
54 if (modelNode == null)
throw new ArgumentNullException(
"modelNode");
55 var node = ObservableModelNode.Create(
this,
"Root", modelNode.Content.IsPrimitive, null, modelNode, modelNode.Content.Type, null);
57 dirtiableViewModels.Add(node, dirtiables.ToList());
60 node.CheckConsistency();
67 var rootNodes =
new List<ObservableModelNode>();
68 foreach (var viewModel
in viewModels)
71 throw new ArgumentException(
@"The view models to combine must contains SingleObservableNode.",
"viewModels");
73 foreach (var dirtiableViewModel
in viewModel.dirtiableViewModels)
74 combinedViewModel.dirtiableViewModels.Add(dirtiableViewModel.Key, dirtiableViewModel.Value.ToList());
77 rootNodes.Add(rootNode);
80 if (rootNodes.Count < 2)
81 throw new ArgumentException(
@"Called CombineViewModels with a collection of view models that is either empty or containt just a single item.",
"viewModels");
83 CombinedObservableNode rootCombinedNode = CombinedObservableNode.Create(combinedViewModel,
"Root", null, typeof(
object), rootNodes, null);
85 rootCombinedNode.Initialize();
86 combinedViewModel.RootNode = rootCombinedNode;
87 return combinedViewModel;
90 internal IReadOnlyCollection<IDirtiableViewModel> GetDirtiableViewModels(
ObservableModelNode node)
101 public IObservableNode RootNode {
get {
return rootNode; }
private set { SetValueUncancellable(ref rootNode, value); } }
107 public Func<SingleObservableNode, object, string> FormatSingleUpdateMessage {
get {
return formatSingleUpdateMessage; } set {
if (value == null)
throw new ArgumentException(
"The value cannot be null."); formatSingleUpdateMessage = value; } }
113 public Func<CombinedObservableNode, object, string> FormatCombinedUpdateMessage {
get {
return formatCombinedUpdateMessage; } set {
if (value == null)
throw new ArgumentException(
"The value cannot be null."); formatCombinedUpdateMessage = value; } }
134 var members = path.Split(
'.');
135 if (members[0] != RootNode.Name)
138 var currentNode = RootNode;
139 foreach (var member
in members.Skip(1))
141 currentNode = currentNode.Children.FirstOrDefault(x => x.Name == member);
142 if (currentNode == null)
151 var members = path.Split(
'.');
152 if (members[0] != RootNode.Name)
155 var currentNode = RootNode;
157 if (combinedNode != null)
159 currentNode = combinedNode.CombinedNodes.OfType<
ObservableModelNode>().Single(x => x.MatchNode(rootModelNode));
161 foreach (var member
in members.Skip(1))
163 currentNode = currentNode.Children.FirstOrDefault(x => x.Name == member);
164 if (currentNode == null)
170 private bool MatchModelRootNode(
IModelNode node)
175 internal bool MatchCombinedRootNode(
IModelNode node)
177 return RootNode is CombinedObservableNode && ((CombinedObservableNode)RootNode).CombinedNodes.OfType<ObservableModelNode>().Any(x => x.MatchNode(node));
182 return MatchModelRootNode(node) || MatchCombinedRootNode(node);
185 internal void NotifyNodeChanged(
string observableNodePath)
187 var handler = NodeChanged;
190 handler(
this,
new NodeChangedArgs(
this, observableNodePath));
194 internal void RegisterAction(
string displayName,
ModelNodePath nodePath,
string observableNodePath,
object index, IReadOnlyCollection<IDirtiableViewModel> dirtiables,
object newValue,
object previousValue)
196 singleNodeActionRegistered =
true;
197 var actionItem =
new ValueChangedActionItem(displayName, observableViewModelService, nodePath, observableNodePath, Identifier, index, dirtiables, modelContainer, previousValue);
198 ActionStack.Add(actionItem);
199 NotifyNodeChanged(observableNodePath);
202 internal void BeginCombinedAction()
204 ActionStack.BeginTransaction();
205 singleNodeActionRegistered =
false;
208 internal void EndCombinedAction(
string displayName,
string observableNodePath,
object value)
210 bool shouldDiscard =
true;
211 foreach (var singleNode
in dirtiableViewModels.Keys)
213 if (singleNode.Owner.singleNodeActionRegistered)
214 shouldDiscard =
false;
216 singleNode.Owner.singleNodeActionRegistered =
false;
221 ActionStack.DiscardTransaction();
225 ActionStack.EndTransaction(displayName, x =>
new CombinedValueChangedActionItem(displayName, observableViewModelService, observableNodePath, Identifier, x));
EventHandler< NodeChangedArgs > NodeChanged
An interface that represents an object which can be in a dirty state (modified since last save)...
A container used to store models and resolve references between them.
A service provider class for view model objects.
A class that provides various services to ObservableViewModel objects
static ObservableViewModel CombineViewModels(IViewModelServiceProvider serviceProvider, ModelContainer modelContainer, IEnumerable< ObservableViewModel > viewModels)
IObservableNode ResolveObservableNode(string path)
ObservableModelNode ResolveObservableModelNode(string path, IModelNode rootModelNode)
This class is an implementation of the DispatcherViewModel class that supports undo/redo of property ...
IObservableNode Root
Gets the root of this node.
ObservableViewModel(IViewModelServiceProvider serviceProvider, ModelContainer modelContainer, IModelNode modelNode, IEnumerable< IDirtiableViewModel > dirtiables)
Initializes a new instance of the ObservableViewModel class.
The IModelNode interface represents a node in a model object. A model object is represented by a grap...
A class describing the path of a node, relative to a root node. The path can cross references...