[reflection] Coop handles icalls in System.Reflection and System.RuntimeTypeHandle...
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Presentation / System / Activities / Presentation / View / WorkflowViewService.cs
1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //----------------------------------------------------------------
4
5 namespace System.Activities.Presentation.View
6 {
7     using System.Activities.Presentation;
8     using System.Activities.Presentation.Internal.PropertyEditing;
9     using System.Activities.Presentation.Model;
10     using System.Activities.Presentation.Services;
11     using System.Activities.XamlIntegration;
12     using System.ComponentModel;
13     using System.Diagnostics.CodeAnalysis;
14     using System.Globalization;
15     using System.Runtime;
16     using System.ServiceModel.Activities;
17     using System.Windows;
18     using System.Windows.Controls;
19     using System.Windows.Media;
20     using System.Collections.Generic;
21
22     [Fx.Tag.XamlVisible(false)]
23     public class WorkflowViewService : ViewService
24     {
25         EditingContext context;
26
27         public WorkflowViewService(EditingContext context)
28         {
29             Fx.Assert(context != null, "The passed in EditingContext is null");
30             this.context = context;
31         }
32         public event EventHandler<ViewCreatedEventArgs> ViewCreated;
33
34         [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
35             Justification = "Catch all exceptions to prevent crash and always return the error view of the designer with the error message")]
36         [SuppressMessage("Reliability", "Reliability108:IsFatalRule",
37             Justification = "Catch all exceptions to prevent crash and always return the error view of the designer with the error message")]
38         public WorkflowViewElement GetViewElement(ModelItem modelItem)
39         {
40             WorkflowViewElement viewElement = null;
41             string errorString = string.Empty;
42             if (modelItem == null)
43             {
44                 return null;
45             }
46
47             try
48             {
49                 // try to make one from the type specified in Designer attribute.
50                 // reuse existing views that are not currently parented
51                 if (modelItem.View != null && ((WorkflowViewElement)modelItem.View).Parent == null)
52                 {
53                     viewElement = (WorkflowViewElement)modelItem.View;
54                 }
55                 else
56                 {
57                     viewElement = CreateViewElement(modelItem);
58                 }
59
60                 // now we successfully got a viewElement, lets initialize it with ModelItem;
61                 if (viewElement != null)
62                 {
63                     viewElement.Context = this.context;
64                     viewElement.ModelItem = modelItem;
65                     ((IModelTreeItem)modelItem).SetCurrentView(viewElement);
66                     viewElement.DataContext = viewElement;
67
68                     // Generate an event that we created a new view element.  This could be used by 
69                     // the Debugger Service to insert a breakpoint on the view element.
70                     if (this.ViewCreated != null)
71                     {
72                         this.ViewCreated(this, new ViewCreatedEventArgs(viewElement));
73                     }
74                 }
75             }
76             // never crash here
77             // always report error to the customer.
78             catch (Exception e)
79             {
80                 errorString = e.ToString();
81             }
82             if (viewElement == null || !(string.IsNullOrEmpty(errorString)))
83             {
84                 viewElement = GenerateErrorElement(modelItem, errorString);
85             }
86             return viewElement;
87         }
88
89         internal static void ShowErrorInViewElement(WorkflowViewElement errorElement, string windowText, string toolTipText)
90         {
91             Grid errorGrid = new Grid();
92             errorGrid.Background = Brushes.Red;
93             errorGrid.Margin = new Thickness(20.0);
94             TextBlock text = new TextBlock();
95             text.Text = windowText;
96             text.Foreground = SystemColors.WindowBrush;
97             errorGrid.Children.Add(text);
98             errorGrid.ToolTip = toolTipText;
99             errorElement.Content = errorGrid;
100         }
101
102         private WorkflowViewElement GenerateErrorElement(ModelItem modelItem, string errorString)
103         {
104             WorkflowViewElement errorElement = new WorkflowViewElement();
105             string errorText = string.Format(CultureInfo.CurrentCulture, SR.CouldNotGenerateView, modelItem.ItemType.Name);
106             ShowErrorInViewElement(errorElement, errorText, errorString);
107             errorElement.Context = this.context;
108             errorElement.ModelItem = modelItem;
109             ((IModelTreeItem)modelItem).SetCurrentView(errorElement);
110             errorElement.DataContext = errorElement;
111             return errorElement;
112         }
113
114         DesignerAttribute GetDesignerAttribute(Type type)
115         {
116             DesignerAttribute designerAttribute = null;
117             //do not return designers for IValueSerializableExpression (i.e. VisualBasicValue or VisualBasicReference
118             if (!typeof(IValueSerializableExpression).IsAssignableFrom(type))
119             {
120                 designerAttribute = GetAttribute<DesignerAttribute>(type);
121             }
122             return designerAttribute;
123         }
124
125         internal static T GetAttribute<T>(Type type) where T : Attribute
126         {
127             T attribute = ExtensibilityAccessor.GetAttribute<T>(type);
128             if (attribute == null && type.IsGenericType)
129             {
130                 attribute = ExtensibilityAccessor.GetAttribute<T>(type.GetGenericTypeDefinition());
131             }
132             return attribute;
133         }
134
135         //Returns the designer type based on the DesignerAttribute associated with the passed in type.
136         internal Type GetDesignerType(Type type)
137         {
138             return GetDesignerType(type, false);
139         }
140
141         internal Type GetDesignerType(Type type, bool throwOnFailure)
142         {
143             Type designerType = null;
144             // Try to identify a designer using the DesignerAttribute, either on the type or from MetaDataStore
145             DesignerAttribute designerAttribute = GetDesignerAttribute(type);
146             if (designerAttribute != null && !String.IsNullOrEmpty(designerAttribute.DesignerTypeName))
147             {
148                 designerType = Type.GetType(designerAttribute.DesignerTypeName, throwOnFailure);
149
150                 //if we have generic activity, check if there is a designer defined at type definition i.e. Assign<T>,
151                 //rather then using a default one (which happens to be ActivityDesigner)
152                 if (type.IsGenericType && Type.Equals(designerType, typeof(ActivityDesigner)))
153                 {
154                     Type genericType = type.GetGenericTypeDefinition();
155                     DesignerAttribute genericDesignerAttribute =
156                         TypeDescriptor.GetAttributes(genericType)[typeof(DesignerAttribute)] as DesignerAttribute;
157                     designerType =
158                         (null == genericDesignerAttribute ?
159                         designerType : Type.GetType(genericDesignerAttribute.DesignerTypeName, throwOnFailure));
160                 }
161             }
162             return designerType;
163         }
164
165         protected WorkflowViewElement CreateViewElement(ModelItem modelItem)
166         {
167             Fx.Assert(modelItem != null, "The passed in ModelItem is null");
168             WorkflowViewElement viewElement = null;
169
170             Type designerType = GetDesignerType(modelItem.ItemType, true);
171
172             if (designerType != null && typeof(WorkflowViewElement).IsAssignableFrom(designerType))
173             {
174                 viewElement = (WorkflowViewElement)Activator.CreateInstance(designerType);
175             }
176             return viewElement;
177         }
178
179         internal WorkflowViewElement CreateDetachedViewElement(ModelItem modelItem)
180         {
181             WorkflowViewElement viewElement = CreateViewElement(modelItem);
182
183             // now we successfully got a viewElement, lets initialize it with ModelItem;
184             if (viewElement != null)
185             {
186                 viewElement.Context = this.context;
187                 viewElement.ModelItem = modelItem;
188                 viewElement.DataContext = viewElement;
189             }
190
191             return viewElement;
192         }
193
194         public override ModelItem GetModel(DependencyObject view)
195         {
196             if (view == null)
197             {
198                 throw FxTrace.Exception.AsError(new ArgumentNullException("view"));
199             }
200
201             if (view is WorkflowViewElement)
202             {
203                 return ((WorkflowViewElement)view).ModelItem;
204             }
205
206             Fx.Assert("we should know if somebody is trying to get model item from thing other than WorkflowViewElement");
207             return null;
208         }
209
210         public override DependencyObject GetView(ModelItem model)
211         {
212             return GetViewElement(model);
213         }
214
215         internal bool ShouldAppearOnBreadCrumb(ModelItem modelItem, bool checkIfCanBeMadeRoot)
216         {
217             bool shouldAppearOnBreadCrumb = false;
218             if (modelItem != null)
219             {
220                 Type designerType = this.GetDesignerType(modelItem.ItemType);
221                 if (null != designerType)
222                 {
223                     if (checkIfCanBeMadeRoot)
224                     {
225                         ActivityDesignerOptionsAttribute options = WorkflowViewService.GetAttribute<ActivityDesignerOptionsAttribute>(modelItem.ItemType);
226                         shouldAppearOnBreadCrumb = (typeof(WorkflowViewElement).IsAssignableFrom(designerType) &&
227                                                    (typeof(ActivityDesigner) != designerType || ActivityDelegateUtilities.HasActivityDelegate(modelItem.ItemType)) &&
228                                                    typeof(WorkflowService) != designerType &&
229                                                    (options == null || options.AllowDrillIn));
230                     }
231                     else
232                     {
233                         shouldAppearOnBreadCrumb = typeof(WorkflowViewElement).IsAssignableFrom(designerType);
234                     }
235                 }
236             }
237             return shouldAppearOnBreadCrumb;
238
239         }   
240     }
241 }