[runtime] Fix corlib out of date error with disabled COM
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Presentation / System / Activities / Presentation / Model / FakeModelPropertyImpl.cs
1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //-----------------------------------------------------------------------------
4
5 namespace System.Activities.Presentation.Model
6 {
7     using System.ComponentModel;
8     using System.Diagnostics;
9     using System.Globalization;
10
11     /// <summary>
12     /// FakeModelPropertyImpl. This class is used with FakeModelItemImpl. it is used to allow full model editing expirience
13     /// without actually modyfing actual model tree. Even though reference to ModelTreeManager is availabe, changes made to object
14     /// using this class are not reflected in actual model. Especially, any changes made here do not affect undo/redo stack.
15     /// see aslo DesignObjectWrapper class for more usage details
16     /// </summary>
17     sealed class FakeModelPropertyImpl : ModelPropertyImpl
18     {
19         IModelTreeItem parentModelTreeItem;
20         FakeModelItemImpl temporaryValue;
21         bool isSettingValue = false;
22
23         public FakeModelPropertyImpl(FakeModelItemImpl parent, PropertyDescriptor propertyDescriptor)
24             : base(parent, propertyDescriptor, false)
25         {
26             this.parentModelTreeItem = (IModelTreeItem)parent;
27         }
28
29         //no collection support
30         public override ModelItemCollection Collection
31         {
32             get { return null; }
33         }
34
35         public override bool IsCollection
36         {
37             get { return false; }
38         }
39
40         //no dictionary support
41         public override ModelItemDictionary Dictionary
42         {
43             get { return null; }
44         }
45
46         public override bool IsDictionary
47         {
48             get { return false; }
49         }
50
51         public override ModelItem Value
52         {
53             get
54             {
55                 ModelItem result = null;
56                 object parentObject = this.parentModelTreeItem.ModelItem.GetCurrentValue();
57                 result = this.StoreValue(this.PropertyDescriptor.GetValue(parentObject));
58                 return result;
59             }
60         }
61
62         public override void ClearValue()
63         {
64             //try setting default value
65             this.SetValue(this.DefaultValue);
66         }
67
68         public override ModelItem SetValue(object value)
69         {
70             //are we already setting value? 
71             if (!isSettingValue)
72             {
73                 try
74                 {
75                     this.isSettingValue = true;
76                     //create new value
77                     this.temporaryValue = this.WrapValue(value);
78                     //is there a value stored already?
79                     if (this.parentModelTreeItem.ModelPropertyStore.ContainsKey(this.Name))
80                     {
81                         //yes - cleanup references
82                         IModelTreeItem item = (IModelTreeItem)this.parentModelTreeItem.ModelPropertyStore[this.Name];
83                         item.RemoveSource(this);
84                         item.RemoveParent(this.parentModelTreeItem.ModelItem);
85                         //and remove it
86                         this.parentModelTreeItem.ModelPropertyStore.Remove(this.Name);
87                     }
88                     //set it onto underlying object
89                     this.PropertyDescriptor.SetValue(this.Parent.GetCurrentValue(), (null != this.temporaryValue ? this.temporaryValue.GetCurrentValue() : null));
90                     //store it in parent's store
91                     this.temporaryValue = this.StoreValue(this.temporaryValue);
92
93                     //notify listeners - notification must be postponed until actual underlying object value is updated, otherwise, listeners might get old value
94                     this.parentModelTreeItem.ModelTreeManager.AddToCurrentEditingScope(new FakeModelNotifyPropertyChange(this.parentModelTreeItem, this.Name));
95                 }
96                 catch (ValidationException e)
97                 {
98                     Trace.WriteLine(e.ToString());
99                     //it is important to rethrow exception here - otherwise, DataGrid will assume operation completed successfully
100                     throw;
101                 }
102                 finally
103                 {
104                     this.isSettingValue = false;
105                 }
106             }
107
108             return this.temporaryValue;
109         }
110
111         FakeModelItemImpl WrapValue(object value)
112         {
113             FakeModelItemImpl wrappedValue = value as FakeModelItemImpl;
114             if (null == wrappedValue && null != value)
115             {
116                 wrappedValue = new FakeModelItemImpl(this.parentModelTreeItem.ModelTreeManager, this.PropertyType, value, (FakeModelItemImpl)this.Parent);
117             }
118             return wrappedValue;
119         }
120
121         FakeModelItemImpl StoreValue(object value)
122         {
123             FakeModelItemImpl wrappedValue = WrapValue(value);
124             if (null != wrappedValue)
125             {
126                 this.parentModelTreeItem.ModelPropertyStore[this.Name] = wrappedValue;
127                 IModelTreeItem modelTreeItem = (IModelTreeItem)wrappedValue;
128                 modelTreeItem.SetSource(this);
129             }
130             else
131             {
132                 ModelItem existing = null;
133                 if (this.parentModelTreeItem.ModelPropertyStore.TryGetValue(this.Name, out existing))
134                 {
135                     IModelTreeItem modelTreeItem = (IModelTreeItem)existing;
136                     modelTreeItem.RemoveSource(this);
137                     modelTreeItem.RemoveParent(this.Parent);
138                 }
139                 this.parentModelTreeItem.ModelPropertyStore.Remove(this.Name);
140             }
141             return wrappedValue;
142         }
143     }
144
145     //helper class - implements change
146     //FakeModelPropery uses instance of this class to notify all listeners that property value has changed. the notification is deffered untill all editing operations
147     //have completed, so the listener will get notified after edit is completed
148     sealed class FakeModelNotifyPropertyChange : ModelChange
149     {
150         IModelTreeItem modelTreeItem;
151         string propertyName;
152
153         public FakeModelNotifyPropertyChange(IModelTreeItem modelTreeItem, string propertyName)
154         {
155             this.modelTreeItem = modelTreeItem;
156             this.propertyName = propertyName;
157         }
158
159         public override string Description
160         {
161             get { return this.GetType().Name; }
162         }
163
164         public override bool Apply()
165         {
166             if (this.modelTreeItem != null)
167             {
168                 EditingContext context = this.modelTreeItem.ModelTreeManager.Context;
169                 //this change shouldn't participate in Undo/Redo
170                 if (null != context && !context.Services.GetService<UndoEngine>().IsUndoRedoInProgress)
171                 {
172                     this.modelTreeItem.OnPropertyChanged(this.propertyName);
173                 }
174             }
175             //return false here - i don't need that change in the change list
176             return false;
177         }
178
179         public override Change GetInverse()
180         {
181             //this change shouldn't participate in Undo/Redo
182             return null;
183         }
184     }
185 }