[corlib] Avoid unnecessary ephemeron array resizes
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Presentation / System / Activities / Presentation / Converters / ModelPropertyEntryToModelItemConverter.cs
1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //----------------------------------------------------------------
4
5 namespace System.Activities.Presentation.Converters
6 {
7     using System;
8     using System.Collections.Generic;
9     using System.Globalization;
10     using System.Linq;
11     using System.Windows;
12     using System.Windows.Data;
13     using System.Activities.Presentation;
14     using System.Activities.Presentation.Model;
15     using System.Activities.Presentation.PropertyEditing;
16     using System.Runtime;
17     using System.Diagnostics.CodeAnalysis;
18
19     public sealed class ModelPropertyEntryToModelItemConverter : IMultiValueConverter, IValueConverter
20     {
21         ModelPropertyEntryToOwnerActivityConverter propertyEntryConverter = new ModelPropertyEntryToOwnerActivityConverter();
22
23         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
24         {
25             PropertyEntry propertyEntry = value as PropertyEntry;
26             if (null == propertyEntry)
27             {
28                 PropertyValue propertyValue = value as PropertyValue;
29                 if (null != propertyValue)
30                 {
31                     propertyEntry = propertyValue.ParentProperty;
32                 }
33             }
34
35             Container result = null;
36             if (null != propertyEntry)
37             {
38                 ModelItem item = null;
39                 ModelItem propertyParentItem = null;
40                 EditingContext context = null;
41                 GetPropertyData(propertyEntry, out item, out propertyParentItem, out context);
42                 result = new Container(item, context, item.View, propertyEntry.PropertyValue);
43             }
44             return result;
45         }
46
47         public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
48         {
49             CategoryEntry category = (CategoryEntry)
50                 values.FirstOrDefault<object>(p => p != null && typeof(CategoryEntry).IsAssignableFrom(p.GetType()));
51
52             FrameworkElement categoryEditorVisual = (FrameworkElement)
53                 values.FirstOrDefault<object>(p => p != null && typeof(FrameworkElement).IsAssignableFrom(p.GetType()));
54  
55             Container result = null;
56
57             if (null != category)
58             {
59                 PropertyEntry property = GetPropertyEntry( category, parameter );
60
61                 if (null != property)
62                 {
63                     ModelItem item = null;
64                     ModelItem propertyParentItem = null;
65                     EditingContext context = null;
66                     GetPropertyData(property, out item, out propertyParentItem, out context);
67                     result = new Container(item, context, item.View, property.PropertyValue);
68
69                     category.PropertyChanged += (sender, e) =>
70                     {
71                         PropertyEntry selectedProperty = this.GetPropertyEntry((CategoryEntry)sender, parameter);
72                         if (null != selectedProperty)
73                         {
74                             this.UpdateCategoryEditorDataContext(selectedProperty, categoryEditorVisual, result);
75                         }
76                     };
77                 }
78             }
79             return result;
80         }
81
82         PropertyEntry GetPropertyEntry(CategoryEntry category, object parameter)
83         {
84             PropertyEntry property = null;
85             IEnumerable<PropertyEntry> properties = (category == null ? null : category.Properties);
86             if (null != properties)
87             {
88                 if (null == parameter)
89                 {
90                     property = properties.ElementAtOrDefault<PropertyEntry>(0);
91                 }
92                 else
93                 {
94                     property = properties.FirstOrDefault<PropertyEntry>(p => string.Equals(p.DisplayName, parameter));
95                 }
96             }
97             return property;
98         }
99
100         void GetPropertyData(PropertyEntry property, out ModelItem activityItem, out ModelItem propertyParentItem, out EditingContext context)
101         {
102             activityItem = (ModelItem)this.propertyEntryConverter.Convert(property, typeof(ModelItem), false, null);
103             propertyParentItem = (ModelItem)this.propertyEntryConverter.Convert(property, typeof(ModelItem), true, null);
104             context = activityItem.GetEditingContext();
105         }
106
107         [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", 
108             Justification = "Catch all exceptions to prevent crash.")]
109         [SuppressMessage("Reliability", "Reliability108:IsFatalRule",
110             Justification = "Catch all exceptions to prevent crash.")]
111         void UpdateCategoryEditorDataContext(PropertyEntry property, FrameworkElement editor, Container context)
112         {
113             try
114             {
115                 editor.DataContext = null;
116                 ModelItem modelItem = null;
117                 ModelItem propertyParentItem = null;
118                 EditingContext editingContext = null;
119                 this.GetPropertyData(property, out modelItem, out propertyParentItem, out editingContext);
120                 context.Context = editingContext;
121                 context.WorkflowViewElement = (null == modelItem ? null : modelItem.View);
122                 context.ModelItem = modelItem;
123                 editor.DataContext = context;
124             }
125             catch (Exception err)
126             {
127                 Fx.Assert(false, err.Message);
128             }
129         }
130
131         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
132         {
133             throw FxTrace.Exception.AsError(new NotSupportedException());
134         }
135
136         public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
137         {
138             throw FxTrace.Exception.AsError(new NotSupportedException());
139         }
140
141
142
143         internal sealed class Container : DependencyObject
144         {
145             public static readonly DependencyProperty ModelItemProperty =
146                 DependencyProperty.Register("ModelItem", typeof(ModelItem), typeof(Container), new UIPropertyMetadata(null));
147
148             public static readonly DependencyProperty ContextProperty =
149                 DependencyProperty.Register("Context", typeof(EditingContext), typeof(Container), new UIPropertyMetadata(null));
150
151             public static readonly DependencyProperty WorkflowViewElementProperty =
152                 DependencyProperty.Register("WorkflowViewElement", typeof(DependencyObject), typeof(Container), new UIPropertyMetadata(null));
153
154             public static readonly DependencyProperty PropertyValueProperty =
155                 DependencyProperty.Register("PropertyValue", typeof(PropertyValue), typeof(Container), new UIPropertyMetadata(null));
156
157             public Container(ModelItem item, EditingContext context, DependencyObject viewElement, PropertyValue value)
158             {
159                 this.ModelItem = item;
160                 this.Context = context;
161                 this.WorkflowViewElement = viewElement;
162                 this.PropertyValue = value;
163             }
164
165             public ModelItem ModelItem
166             {
167                 get { return (ModelItem)GetValue(ModelItemProperty); }
168                 set { SetValue(ModelItemProperty, value); }
169             }
170
171             public EditingContext Context
172             {
173                 get { return (EditingContext)GetValue(ContextProperty); }
174                 set { SetValue(ContextProperty, value); }
175             }
176
177             public DependencyObject WorkflowViewElement
178             {
179                 get { return (DependencyObject)GetValue(WorkflowViewElementProperty); }
180                 set { SetValue(WorkflowViewElementProperty, value); }
181             }
182
183             public PropertyValue PropertyValue
184             {
185                 get { return (PropertyValue)GetValue(PropertyValueProperty); }
186                 set { SetValue(PropertyValueProperty, value); }
187             }
188
189         }
190     }
191 }