4 using System.Collections.Generic;
5 using System.ComponentModel;
8 using SiliconStudio.Core.Extensions;
10 using SiliconStudio.Quantum;
12 namespace SiliconStudio.Presentation.Quantum
16 private readonly List<SingleObservableNode> combinedNodes;
17 private readonly List<object> combinedNodeInitialValues;
18 private readonly HashSet<object> distinctCombinedNodeInitialValues;
19 private readonly
int? order;
21 protected static readonly HashSet<CombinedObservableNode> ChangedNodes =
new HashSet<CombinedObservableNode>();
28 : base(ownerViewModel, parentNode, index)
30 this.combinedNodes =
new List<SingleObservableNode>(combinedNodes);
32 DisplayName = this.combinedNodes.First().DisplayName;
34 combinedNodeInitialValues =
new List<object>();
35 distinctCombinedNodeInitialValues =
new HashSet<object>();
37 bool isReadOnly =
false;
38 bool isVisible =
false;
39 bool nullOrder =
false;
41 foreach (var node
in this.combinedNodes)
49 if (node.Order == null)
52 if (order == node.Order || (!nullOrder && order == null))
55 combinedNodeInitialValues.Add(node.Value);
56 distinctCombinedNodeInitialValues.Add(node.Value);
57 node.PropertyChanged += NodePropertyChanged;
59 IsReadOnly = isReadOnly;
60 IsVisible = isVisible;
62 ResetInitialValues =
new AnonymousCommand(ServiceProvider, () => { Owner.BeginCombinedAction(); CombinedNodes.Zip(combinedNodeInitialValues).ForEach(x => x.Item1.Value = x.Item2); Refresh(); Owner.EndCombinedAction(Owner.FormatCombinedUpdateMessage(
this, null), Path, null); });
66 internal void Initialize()
71 private void Initialize(
bool isUpdating)
73 var commandGroups =
new Dictionary<string, List<ModelNodeCommandWrapper>>();
74 foreach (var node
in combinedNodes)
76 foreach (var command
in node.Commands)
78 var list = commandGroups.GetOrCreateValue(command.Name);
79 list.Add((ModelNodeCommandWrapper)command);
83 foreach (var commandGroup
in commandGroups)
86 if (commandGroup.Value.Any(x => x.CombineMode != mode))
87 throw new InvalidOperationException(
string.Format(
"Inconsistent combine mode among command {0}", commandGroup.Key));
89 var shouldCombine = mode != CombineMode.DoNotCombine && (mode == CombineMode.AlwaysCombine || commandGroup.Value.Count == combinedNodes.Count);
93 var command =
new CombinedNodeCommandWrapper(ServiceProvider, commandGroup.Key, Path, Owner.Identifier, commandGroup.Value);
98 if (!HasList || HasDictionary)
100 var commonChildren = GetCommonChildren();
101 GenerateChildren(commonChildren, isUpdating);
105 var allChildren = GetAllChildrenByValue();
106 if (allChildren != null)
108 GenerateListChildren(allChildren, isUpdating);
112 if (Owner.ObservableViewModelService != null)
114 var data = Owner.ObservableViewModelService.RequestAssociatedData(
this, isUpdating);
115 SetValue(ref associatedData, data,
"AssociatedData");
117 CheckDynamicMemberConsistency();
122 if (ChangeInProgress)
124 ChangedNodes.Add(
this);
128 internal static CombinedObservableNode
Create(ObservableViewModel ownerViewModel,
string name, CombinedObservableNode parent, Type contentType,
IEnumerable<SingleObservableNode> combinedNodes,
object index)
130 var node = (CombinedObservableNode)Activator.CreateInstance(typeof(CombinedObservableNode<>).MakeGenericType(contentType), ownerViewModel, name, parent, combinedNodes, index);
135 public override sealed
bool IsPrimitive {
get {
return CombinedNodes.All(x => x.IsPrimitive); } }
137 public IReadOnlyCollection<SingleObservableNode> CombinedNodes {
get {
return combinedNodes; } }
139 public bool HasMultipleValues {
get {
if (Type.IsValueType || Type == typeof(
string))
return CombinedNodes.Any(x => !Equals(x.Value, CombinedNodes.First().Value));
return Children.Any(x => ((
CombinedObservableNode)x).HasMultipleValues); } }
141 public bool HasMultipleInitialValues {
get {
if (Type.IsValueType || Type == typeof(
string))
return distinctCombinedNodeInitialValues.Count > 1;
return Children.Any(x => ((
CombinedObservableNode)x).HasMultipleInitialValues); } }
147 public override int? Order {
get {
return order; } }
150 public override sealed
bool HasList {
get {
return CombinedNodes.First().HasList; } }
153 public override sealed
bool HasDictionary {
get {
return CombinedNodes.First().HasDictionary; } }
162 if (Parent == null)
throw new InvalidOperationException(
"The node to refresh can be a root node.");
164 OnPropertyChanging(
"TypedValue",
"HasMultipleValues",
"IsPrimitive",
"HasList",
"HasDictionary");
165 if (CombinedNodes.Any(x => x != null))
168 parent.RemoveChild(
this);
170 if (AreCombinable(CombinedNodes))
174 foreach (var child
in Children.ToList())
182 parent.AddChild(
this);
184 OnPropertyChanged(
"TypedValue",
"HasMultipleValues",
"IsPrimitive",
"HasList",
"HasDictionary");
189 bool firstNode =
true;
194 foreach (var node
in nodes)
205 if (node.Type != type)
207 if (!ignoreNameConstraint && node.Name != name)
209 if (!Equals(node.Index, index))
216 private void GenerateChildren(
IEnumerable<KeyValuePair<
string, List<SingleObservableNode>>> commonChildren,
bool isUpdating)
218 foreach (var children
in commonChildren)
220 var contentType = children.Value.First().Type;
221 var index = children.Value.First().Index;
223 child.Initialize(isUpdating);
228 private void GenerateListChildren(
IEnumerable<KeyValuePair<
object, List<SingleObservableNode>>> allChildren,
bool isUpdating)
230 int currentIndex = 0;
231 foreach (var children
in allChildren)
233 if (!ShouldCombine(children.Value, CombinedNodes.Count,
"(ListItem)",
true))
236 var contentType = children.Value.First().Type;
237 var name = string.Format(
"Item {0}", currentIndex);
238 CombinedObservableNode child = Create(Owner, name,
this, contentType, children.Value, currentIndex);
239 child.Initialize(isUpdating);
240 child.DisplayName = name;
248 var allChildNodes =
new Dictionary<string, List<SingleObservableNode>>();
249 foreach (var singleNode
in CombinedNodes)
251 foreach (var observableNode
in singleNode.Children)
253 var child = (SingleObservableNode)observableNode;
254 var list = allChildNodes.GetOrCreateValue(child.Name);
259 return allChildNodes.Where(x => ShouldCombine(x.Value, CombinedNodes.Count, x.Key));
262 private static bool ShouldCombine(List<SingleObservableNode> nodes,
int combineCount,
string name,
bool ignoreNameConstraint =
false)
266 if (!AreCombinable(nodes, ignoreNameConstraint))
269 foreach (var node
in nodes)
271 if (combineMode == null)
274 if (combineMode != node.CombineMode)
275 throw new InvalidOperationException(
string.Format(
"Inconsistent values of CombineMode in single nodes for child '{0}'", name));
281 return combineMode == CombineMode.AlwaysCombine || nodes.Count == combineCount;
286 var allChildNodes =
new List<KeyValuePair<object, List<SingleObservableNode>>>();
287 foreach (var singleNode
in CombinedNodes)
289 var usedSlots =
new List<List<SingleObservableNode>>();
290 foreach (var observableNode
in singleNode.Children)
292 var child = (SingleObservableNode)observableNode;
293 if (!child.Type.IsValueType && child.Type != typeof(
string))
296 var list = allChildNodes.FirstOrDefault(x => Equals(x.Key, child.Value) && !usedSlots.Contains(x.Value)).Value;
299 list =
new List<SingleObservableNode>();
300 allChildNodes.Add(
new KeyValuePair<object, List<SingleObservableNode>>(child.Value, list));
307 return allChildNodes;
314 : base(ownerViewModel, name, parentNode, combinedNodes, index)
316 DependentProperties.Add(Tuple.Create(
"TypedValue",
"Value"));
326 return HasMultipleValues ?
default(T) : (T)CombinedNodes.First().Value;
330 Owner.BeginCombinedAction();
331 ChangeInProgress =
true;
332 CombinedNodes.Where(x => x.IsVisible).ForEach(x => x.Value = value);
333 var changedNodes = ChangedNodes.Where(x => x !=
this).ToList();
334 ChangedNodes.Clear();
335 ChangeInProgress =
false;
337 changedNodes.ForEach(x => x.Refresh());
338 string displayName = Owner.FormatCombinedUpdateMessage(
this, value);
339 Owner.EndCombinedAction(displayName, Path, value);
344 public override Type Type {
get {
return typeof(T); } }
347 public override sealed
object Value {
get {
return TypedValue; } set { TypedValue = (T)value; } }
An implementation of CommandBase that route Execute calls to a given anonymous method.
An interface representing an implementation of ICommand with additional properties.
static bool ChangeInProgress
CombineMode
An enum that describes what to do with a node or a command when combining view models.
Creates a new file, always. If a file exists, the function overwrites the file, clears the existing a...
static bool AreCombinable(IEnumerable< SingleObservableNode > nodes, bool ignoreNameConstraint=false)
CombinedObservableNode(ObservableViewModel ownerViewModel, string name, CombinedObservableNode parentNode, IEnumerable< SingleObservableNode > combinedNodes, object index)
CombinedObservableNode(ObservableViewModel ownerViewModel, string name, CombinedObservableNode parentNode, IEnumerable< SingleObservableNode > combinedNodes, object index)