Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
ValueChangedActionItem.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 
6 using SiliconStudio.Core.Reflection;
7 using SiliconStudio.Presentation.ViewModel;
8 using SiliconStudio.Presentation.ViewModel.ActionStack;
9 using SiliconStudio.Quantum;
10 
11 namespace SiliconStudio.Presentation.Quantum
12 {
14  {
15  private ObservableViewModelService service;
16  private ModelContainer modelContainer;
17  private ModelNodePath nodePath;
18  private string observableNodePath;
19  private readonly ObservableViewModelIdentifier identifier;
20 
21  private object index;
22  private object previousValue;
23 
24  public ValueChangedActionItem(string name, ObservableViewModelService service, ModelNodePath nodePath, string observableNodePath, ObservableViewModelIdentifier identifier, object index, IEnumerable<IDirtiableViewModel> dirtiables, ModelContainer modelContainer, object previousValue)
25  : base(name, dirtiables)
26  {
27  if (service == null) throw new ArgumentNullException("service");
28  if (!nodePath.IsValid) throw new InvalidOperationException("Unable to retrieve the path of the modified node.");
29  this.service = service;
30  this.modelContainer = modelContainer;
31  this.nodePath = nodePath;
32  this.index = index;
33  this.observableNodePath = observableNodePath;
34  this.identifier = identifier;
35  this.previousValue = previousValue;
36  }
37 
38  public string ObservableNodePath { get { return observableNodePath; } }
39 
40  protected override void FreezeMembers()
41  {
42  service = null;
43  modelContainer = null;
44  nodePath = null;
45  observableNodePath = null;
46  index = null;
47  }
48 
49  /// <inheritdoc/>
50  protected override void UndoAction()
51  {
52  var node = nodePath.GetNode();
53  if (node == null)
54  throw new InvalidOperationException("Unable to retrieve the node to modify in this undo process.");
55 
56  var currentValue = GetValue(node, index);
57  bool setByObservableNode = false;
58 
59  var observableViewModel = service.ViewModelProvider != null ? service.ViewModelProvider(identifier) : null;
60  if (observableViewModel != null && !observableViewModel.MatchRootNode(nodePath.RootNode))
61  observableViewModel = null;
62 
63  if (observableViewModel != null)
64  {
65  SingleObservableNode observableNode = observableViewModel.ResolveObservableModelNode(observableNodePath, nodePath.RootNode);
66  if (observableNode != null)
67  {
68  observableNode.Value = previousValue;
69  setByObservableNode = true;
70  }
71  }
72 
73  if (!setByObservableNode)
74  {
75  SetValue(node, index, previousValue);
76  // Update the view model nodes in case the graph of the object is modified by this value change
77  modelContainer.UpdateReferences(node);
78  }
79 
80  previousValue = currentValue;
81  }
82 
83  /// <inheritdoc/>
84  protected override void RedoAction()
85  {
86  // Once we have un-done, the previous value is updated so Redo is just Undoing the Undo
87  UndoAction();
88  }
89 
90  private static void SetValue(IModelNode node, object index, object value)
91  {
92  // Index should be used only for items in collection of primitive type, where the whole list is fully reresented by a single node. So we test that we're not in another root object
93  if (index != null)
94  {
95  var collectionDescriptor = node.Content.Descriptor as CollectionDescriptor;
96  var dictionaryDescriptor = node.Content.Descriptor as DictionaryDescriptor;
97  if (collectionDescriptor != null)
98  {
99  collectionDescriptor.SetValue(node.Content.Value, (int)index, value);
100  }
101  else if (dictionaryDescriptor != null)
102  {
103  dictionaryDescriptor.SetValue(node.Content.Value, index, value);
104  }
105  else
106  throw new NotSupportedException("Unable to undo the change, the collection is unsupported");
107  }
108  else
109  {
110  node.Content.Value = value;
111  }
112  }
113 
114  private static object GetValue(IModelNode node, object index)
115  {
116  if (index != null)
117  {
118  var collectionDescriptor = node.Content.Descriptor as CollectionDescriptor;
119  var dictionaryDescriptor = node.Content.Descriptor as DictionaryDescriptor;
120  if (collectionDescriptor != null)
121  {
122  return collectionDescriptor.GetValue(node.Content.Value, (int)index);
123  }
124  if (dictionaryDescriptor != null)
125  {
126  return dictionaryDescriptor.GetValue(node.Content.Value, index);
127  }
128 
129  throw new NotSupportedException("Unable to undo the change, the collection is unsupported");
130  }
131 
132  return node.Content.Value;
133  }
134  }
135 }
Provides a descriptor for a System.Collections.ICollection.
A container used to store models and resolve references between them.
override void FreezeMembers()
Invoked by Freeze before setting IsFrozen to true.
bool IsValid
Gets whether this path is a valid path.
Provides a descriptor for a System.Collections.IDictionary.
override void UndoAction()
Invoked by Undo after setting IsDone to true.
An abstact class that inherits from ActionItem and can be used to manage actions related to an IDirti...
A class that provides various services to ObservableViewModel objects
override void RedoAction()
Invoked by Redo after setting IsDone to true.
ValueChangedActionItem(string name, ObservableViewModelService service, ModelNodePath nodePath, string observableNodePath, ObservableViewModelIdentifier identifier, object index, IEnumerable< IDirtiableViewModel > dirtiables, ModelContainer modelContainer, object previousValue)
The IModelNode interface represents a node in a model object. A model object is represented by a grap...
Definition: IModelNode.cs:16
A class describing the path of a node, relative to a root node. The path can cross references...