Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Activities.Core.Presentation / System / ServiceModel / Activities / Presentation / ContentCorrelationTypeExpander.xaml.cs
1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //----------------------------------------------------------------
4
5 namespace System.ServiceModel.Activities.Presentation
6 {
7     using System.Activities.Presentation;
8     using System.Collections.Generic;
9     using System.Reflection;
10     using System.Runtime.Serialization;
11     using System.Windows;
12     using System.Windows.Controls;
13     using System.Windows.Input;
14     using System.Windows.Threading;
15     using System.Xml;
16     using System.Linq;
17     using System.Collections;
18     using System.Xml.Linq;
19
20     partial class ContentCorrelationTypeExpander
21     {
22         static readonly DependencyPropertyKey IsSelectionValidPropertyKey = DependencyProperty.RegisterReadOnly(
23             "IsSelectionValid",
24             typeof(bool),
25             typeof(ContentCorrelationTypeExpander),
26             new UIPropertyMetadata(false, OnIsSelectionValidChanged));
27
28         public static readonly DependencyProperty IsSelectionValidProperty = IsSelectionValidPropertyKey.DependencyProperty;
29
30         public static readonly RoutedEvent IsSelectionValidChangedEvent = EventManager.RegisterRoutedEvent(
31             "IsSelectionValidChanged",
32             RoutingStrategy.Bubble,
33             typeof(RoutedEventHandler),
34             typeof(ContentCorrelationTypeExpander));
35
36         public static readonly RoutedEvent SelectionChangedEvent = EventManager.RegisterRoutedEvent(
37             "SelectionChanged",
38             RoutingStrategy.Bubble,
39             typeof(RoutedEventHandler),
40             typeof(ContentCorrelationTypeExpander));
41
42         public static readonly DependencyProperty TypesToExpandProperty = DependencyProperty.Register(
43             "TypesToExpand",
44             typeof(IList<ExpanderTypeEntry>),
45             typeof(ContentCorrelationTypeExpander),
46             new UIPropertyMetadata(null, OnTypesToExpandChanged));
47
48         static readonly DependencyPropertyKey SelectedTypeEntryPropertyKey = DependencyProperty.RegisterReadOnly(
49             "SelectedTypeEntry", 
50             typeof(ExpanderTypeEntry), 
51             typeof(ContentCorrelationTypeExpander), 
52             new UIPropertyMetadata(null));
53
54         public static readonly DependencyProperty SelectedTypeEntryProperty = SelectedTypeEntryPropertyKey.DependencyProperty;
55
56         static readonly Type[] PrimitiveTypesInXPath = new Type[]
57             {
58                 typeof(DateTime),
59                 typeof(TimeSpan),
60                 typeof(XmlQualifiedName),                
61                 typeof(Uri),                
62                 typeof(Guid),
63                 typeof(XmlElement),
64                 typeof(string),
65                 typeof(object),
66                 typeof(Decimal),
67                 typeof(XElement),
68             };
69
70         MemberInfo[] path = null;
71         Type selectedType = null;       
72
73         public ContentCorrelationTypeExpander()
74         {
75             InitializeComponent();
76         }
77
78         public event RoutedEventHandler IsSelectionValidChanged
79         {
80             add
81             {
82                 AddHandler(IsSelectionValidChangedEvent, value);
83             }
84             remove
85             {
86                 RemoveHandler(IsSelectionValidChangedEvent, value);
87             }
88         }
89
90         public event RoutedEventHandler SelectionChanged
91         {
92             add
93             {
94                 AddHandler(SelectionChangedEvent, value);
95             }
96             remove
97             {
98                 RemoveHandler(SelectionChangedEvent, value);
99             }
100         }
101         public bool IsSelectionValid
102         {
103             get { return (bool)GetValue(IsSelectionValidProperty); }
104             private set { SetValue(IsSelectionValidPropertyKey, value); }
105         }
106
107         public IList<ExpanderTypeEntry> TypesToExpand
108         {
109             get { return (IList<ExpanderTypeEntry>)GetValue(TypesToExpandProperty); }
110             set { SetValue(TypesToExpandProperty, value); }
111         }
112
113         public ExpanderTypeEntry SelectedTypeEntry
114         {
115             get { return (ExpanderTypeEntry)GetValue(SelectedTypeEntryProperty); }
116             private set { SetValue(SelectedTypeEntryPropertyKey, value); }
117         }
118
119         public Type GetSelectedType()
120         {
121             return this.selectedType;
122         }
123
124         public MemberInfo[] GetMemberPath()
125         {
126             return this.path;
127         }
128
129         void RaiseSelectionValidChanged()
130         {
131             this.RaiseEvent(new RoutedEventArgs(IsSelectionValidChangedEvent, this));
132         }
133
134         void OnTypesToExpandChanged()
135         {
136             this.typeExpander.ItemsSource = this.TypesToExpand;
137             this.emptyContent.Visibility = null == this.TypesToExpand || 0 == this.TypesToExpand.Count ? Visibility.Visible : Visibility.Collapsed;
138         }
139
140         void OnTypeExpanderLoaded(object sender, RoutedEventArgs e)
141         {
142             this.typeExpander.Focus();
143         }
144
145         void OnTreeViewItemLoaded(object sender, RoutedEventArgs e)
146         {
147             var item = (TreeViewItem)sender;
148             if (null != item.Header)
149             {
150                 if (item.Header is ExpanderTypeEntry)
151                 {
152                     item.IsExpanded = true;
153                 }
154                 else if (item.Header is Type)
155                 {
156                     var type = (Type)item.Header;
157                     item.IsExpanded = true;
158                 }
159             }
160         }
161
162         void OnTreeViewItemMouseAccept(object sender, MouseButtonEventArgs e)
163         {
164             var item = sender as TreeViewItem;
165             if (null != item && item.Header is ExpanderTypeEntry)
166             {
167                 this.SelectedTypeEntry = (ExpanderTypeEntry)item.Header;
168             }
169             if (null != item && item.IsSelected && item.IsSelectionActive)
170             {
171                 this.Accept(item);
172                 e.Handled = true;
173             }
174         }
175
176         void OnTreeViewItemKeyboardAccept(object sender, KeyEventArgs e)
177         {
178             var item = sender as TreeViewItem;
179             if (null != item && item.Header is ExpanderTypeEntry)
180             {
181                 this.SelectedTypeEntry = (ExpanderTypeEntry)item.Header;
182             }
183             if (null != item && item.IsSelected && item.IsSelectionActive && Key.Enter == e.Key && Keyboard.Modifiers == ModifierKeys.None)
184             {
185                 this.Accept(item);
186                 e.Handled = true;
187             }
188         }
189
190         void Accept(TreeViewItem item)
191         {
192             bool isType = item.Header is ExpanderTypeEntry;
193             bool isMember  = item.Header is MemberInfo;
194             if (isMember)
195             {
196                 var members = new List<MemberInfo>(1);
197                 while (null != item && item.Header is MemberInfo)
198                 {
199                     var member = (MemberInfo)item.Header;
200                     members.Insert(0, member);
201
202                     if (item.Tag is TreeViewItem)
203                     {
204                         item = (TreeViewItem)item.Tag;
205                     }
206                     else
207                     {
208                         item = null;
209                     }
210                 }
211                 this.SelectedTypeEntry = (ExpanderTypeEntry)item.Header;
212                 this.selectedType = this.SelectedTypeEntry.TypeToExpand;
213                 this.path = members.ToArray();
214             }
215             else if (isType)
216             {
217                 this.SelectedTypeEntry = (ExpanderTypeEntry)item.Header;
218                 this.selectedType = this.SelectedTypeEntry.TypeToExpand;
219                 this.path = new MemberInfo[0];
220             }
221             else
222             {
223                 this.SelectedTypeEntry = null;
224                 this.selectedType = null;
225                 this.path = null;
226             }
227             this.IsSelectionValid = isType || isMember;
228             this.RaiseEvent(new RoutedEventArgs(SelectionChangedEvent, this));
229         }
230
231         //The following types are considered as primitives as far as XPath generation is concerned and shouldn't be expanded any more
232         // 1. CLR built-in types 
233         // 2. Byte array, DateTime, TimeSpan, GUID, Uri, XmlQualifiedName, XmlElement and XmlNode array [This includes XElement and XNode array from .NET 3.5] 
234         // 3. Enums 
235         // 4. Arrays and Collection classes including List<T>, Dictionary<K,V> and Hashtable (Anything that implements IEnumerable or IDictionary or is an array is treated as a collection).
236         // 5. Type has [CollectionDataContract] attribute
237         internal static bool IsPrimitiveTypeInXPath(Type type)
238         {
239             return ((type.IsPrimitive) || type.IsEnum || PrimitiveTypesInXPath.Any((item => item == type))
240                 || (typeof(IEnumerable).IsAssignableFrom(type)) || typeof(IDictionary).IsAssignableFrom(type) || type.IsArray
241                 || (type.GetCustomAttributes(typeof(CollectionDataContractAttribute), false).Length > 0));
242         }
243
244         static void OnIsSelectionValidChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
245         {
246             ((ContentCorrelationTypeExpander)sender).RaiseSelectionValidChanged();
247         }
248
249         static void OnTypesToExpandChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
250         {
251             var control = (ContentCorrelationTypeExpander)sender;
252             control.Dispatcher.BeginInvoke(new Action(() => { control.OnTypesToExpandChanged(); }), DispatcherPriority.Render);
253         }
254     }
255
256     internal sealed class TypeEntryContainer
257     {
258         public string DisplayText { get; set; }
259         public IList<ExpanderTypeEntry> Items { get; set; }
260
261         public override string ToString()
262         {
263             return this.DisplayText ?? base.ToString();
264         }
265     }
266
267     internal sealed class ExpanderTypeEntry : DependencyObject
268     {
269         public static readonly DependencyProperty NameProperty = DependencyProperty.Register(
270             "Name",
271             typeof(string),
272             typeof(ExpanderTypeEntry),
273             new UIPropertyMetadata(string.Empty));
274
275         public static readonly DependencyProperty TypeToExpandProperty = DependencyProperty.Register(
276             "TypeToExpand",
277             typeof(Type),
278             typeof(ExpanderTypeEntry),
279             new UIPropertyMetadata(null));
280
281         public static readonly DependencyProperty TagProperty = DependencyProperty.Register(
282             "Tag",
283             typeof(object),
284             typeof(ExpanderTypeEntry),
285             new UIPropertyMetadata(null));
286
287         public string Name
288         {
289             get { return (string)GetValue(NameProperty); }
290             set { SetValue(NameProperty, value); }
291         }
292
293         public Type TypeToExpand
294         {
295             get { return (Type)GetValue(TypeToExpandProperty); }
296             set { SetValue(TypeToExpandProperty, value); }
297         }
298
299         public Type[] TypeToExpandSource
300         {
301             get { return new Type[] { this.TypeToExpand }; }
302         }
303
304         public object Tag
305         {
306             get { return GetValue(TagProperty); }
307             set { SetValue(TagProperty, value); }
308         }
309
310         public override string ToString()
311         {
312             return this.Name ?? "<null>";
313         }
314     }
315 }