1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //------------------------------------------------------------
5 namespace System.Activities.Presentation.Toolbox
8 using System.Activities.Presentation.Utility;
9 using System.Activities.Presentation.View;
10 using System.Collections.Generic;
11 using System.ComponentModel;
12 using System.Diagnostics.CodeAnalysis;
14 using System.Drawing.Design;
15 using System.Globalization;
17 using System.Reflection;
18 using System.Runtime.InteropServices;
20 using System.Windows.Media;
21 using System.Windows.Media.Imaging;
23 // This class is a wrapper for ToolboxItem objects. It adds support
24 // for cate----zation of toolbox items. ResolveToolboxItem method
25 // establishes link between actual ToolboxItem instance and Tool representation
26 // in the toolbox (via qualified assembly and type name properties)
28 public sealed class ToolboxItemWrapper : INotifyPropertyChanged
33 string customDisplayName;
34 string defaultDisplayName;
36 ToolboxItem toolboxItem;
38 IDataObject dataObject;
39 //LogPixelsXIndex and LogPixelsYIndex are the parameters you pass to GetDeviceCaps to get the current monitor resolution, they are constant.
40 private const int LogPixelsXIndex = 88;
41 private const int LogPixelsYIndex = 90;
42 private const int defaultDpi = 96;
44 public ToolboxItemWrapper()
45 : this(string.Empty, string.Empty, string.Empty, string.Empty)
49 public ToolboxItemWrapper(Type toolType)
50 : this(toolType, string.Empty)
54 public ToolboxItemWrapper(Type toolType, string displayName)
55 : this(toolType, string.Empty, displayName)
59 public ToolboxItemWrapper(Type toolType, string bitmapName, string displayName)
60 : this(toolType.FullName, toolType.Assembly.FullName, bitmapName, displayName)
64 public ToolboxItemWrapper(string toolName, string assemblyName, string bitmapName, string displayName)
65 : this(toolName, assemblyName, bitmapName, displayName, null)
69 internal ToolboxItemWrapper(string toolName, string assemblyName, string bitmapName, string displayName, IDataObject dataObject)
71 this.ToolName = toolName;
72 this.AssemblyName = assemblyName;
73 this.BitmapName = bitmapName;
74 this.DisplayName = displayName;
75 this.defaultDisplayName = string.Empty;
76 this.dataObject = dataObject;
78 public event PropertyChangedEventHandler PropertyChanged;
80 internal ToolboxItem ToolboxItem
82 get { return this.toolboxItem; }
85 if (this.toolboxItem != value)
87 this.toolboxItem = value;
88 RaisePropertyChanged("IsValid");
89 RaisePropertyChanged("ToolboxItem");
98 return (null != this.toolboxItem);
102 public string ToolName
104 get { return this.toolName; }
107 if (null != this.toolboxItem)
109 throw FxTrace.Exception.AsError(new InvalidOperationException(SR.ToolboxItemFrozenDescription));
111 bool isChanged = !string.Equals(value, this.toolName);
114 this.toolName = value;
115 RaisePropertyChanged("ToolName");
116 this.ToolboxItem = null;
121 public string AssemblyName
123 get { return this.assemblyName; }
126 if (null != this.toolboxItem)
128 throw FxTrace.Exception.AsError(new InvalidOperationException(SR.ToolboxItemFrozenDescription));
130 bool isChanged = !string.Equals(value, this.assemblyName);
133 this.assemblyName = value;
134 RaisePropertyChanged("AssemblyName");
135 this.ToolboxItem = null;
140 public string BitmapName
142 get { return this.bitmapName; }
145 bool isChanged = !string.Equals(value, this.bitmapName);
148 this.bitmapName = value;
149 RaisePropertyChanged("BitmapName");
155 internal IDataObject DataObject
159 return this.dataObject;
164 this.dataObject = value;
170 get { return this.ToolboxItem.Bitmap; }
173 public string DisplayName
177 return this.ToolboxItem != null ? this.ToolboxItem.DisplayName : this.customDisplayName;
181 bool isChanged = !string.Equals(value, this.customDisplayName);
184 this.customDisplayName = value;
185 ChangeToolboxDisplayName();
186 RaisePropertyChanged("DisplayName");
191 [SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "By design.")]
194 get { return this.toolType; }
197 bool isChanged = !Type.Equals(this.toolType, value);
200 this.toolType = value;
201 RaisePropertyChanged("Type");
206 internal bool ResolveToolboxItem()
208 if (null != this.ToolboxItem)
214 if (null == this.AssemblyName || null == this.ToolName)
216 throw FxTrace.Exception.AsError(new ArgumentNullException(null == AssemblyName ? "AssemblyName" : "ToolName"));
219 Assembly toolAssembly = Assembly.Load(this.AssemblyName);
220 Type discoveredToolType = toolAssembly.GetType(this.ToolName, true, true);
221 ValidateTool(discoveredToolType);
222 ToolboxItemAttribute[] toolboxItemAttributes
223 = discoveredToolType.GetCustomAttributes(typeof(ToolboxItemAttribute), true) as ToolboxItemAttribute[];
224 ToolboxItem instance = null;
225 if (0 != toolboxItemAttributes.Length)
228 Activator.CreateInstance(toolboxItemAttributes[0].ToolboxItemType) as ToolboxItem;
232 instance = new ToolboxItem(discoveredToolType);
234 this.ToolboxItem = instance;
235 this.defaultDisplayName = instance.DisplayName;
236 this.defaultBitmap = instance.Bitmap;
238 ChangeToolboxDisplayName();
239 this.Type = discoveredToolType;
244 this.ToolboxItem = null;
250 internal static Bitmap CreateBitmapFromDrawingBrush(DrawingBrush resource)
252 if (resource == null)
257 const int defaultPixelWidth = 16;
258 const int defaultPixelHeight = 16;
259 double dpiX = GetSystemDpi(LogPixelsXIndex);
260 double dpiY = GetSystemDpi(LogPixelsYIndex);
261 int pixelWidth = (int)(defaultPixelWidth * dpiX / defaultDpi);
262 int pixelHeight = (int)(defaultPixelHeight * dpiY / defaultDpi);
263 var renderTargetBitmap = new RenderTargetBitmap(pixelWidth, pixelHeight, dpiX, dpiY, PixelFormats.Pbgra32);
264 var drawingVisual = new DrawingVisual();
265 using (var context = drawingVisual.RenderOpen())
267 context.DrawRectangle(((DrawingBrush)resource), null, new Rect(0, 0, defaultPixelWidth, defaultPixelHeight));
270 renderTargetBitmap.Render(drawingVisual);
271 MemoryStream bitmapStream = new MemoryStream();
272 BitmapEncoder bitmapEncode = new PngBitmapEncoder
274 Interlace = PngInterlaceOption.Off,
276 bitmapEncode.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
277 bitmapEncode.Save(bitmapStream);
278 //Reposition the MemoryStream pointer to the start of the stream after the save
279 bitmapStream.Position = 0;
280 Bitmap bitmap = new Bitmap(bitmapStream);
284 internal static Bitmap GetBitmapFromResource(string resourceString)
286 DrawingBrush drawingBrush = IconHelper.GetBrushFromResource(resourceString);
287 return CreateBitmapFromDrawingBrush(drawingBrush);
294 if (this.toolboxItem != null)
296 if (!string.IsNullOrEmpty(this.BitmapName))
298 this.toolboxItem.Bitmap = new Bitmap(this.BitmapName);
302 Bitmap bitmap = GetBitmapFromResource(this.toolboxItem.TypeName);
305 this.toolboxItem.Bitmap = bitmap;
309 if (WorkflowDesignerIcons.IsDefaultCutomActivitySetByUser)
311 this.toolboxItem.Bitmap = CreateBitmapFromDrawingBrush(WorkflowDesignerIcons.Activities.DefaultCustomActivity);
313 else if (WorkflowDesignerIcons.Activities.ToolboxDefaultCustomActivity != null)
315 this.toolboxItem.Bitmap = CreateBitmapFromDrawingBrush(WorkflowDesignerIcons.Activities.ToolboxDefaultCustomActivity);
319 this.toolboxItem.Bitmap = this.defaultBitmap;
325 catch (ArgumentException)
327 this.toolboxItem.Bitmap = this.defaultBitmap;
330 RaisePropertyChanged("ToolboxItem");
331 RaisePropertyChanged("Bitmap");
334 void ChangeToolboxDisplayName()
336 if (null != this.toolboxItem)
338 if (!string.IsNullOrEmpty(this.customDisplayName))
340 this.toolboxItem.DisplayName = this.customDisplayName;
344 this.toolboxItem.DisplayName = this.defaultDisplayName;
346 RaisePropertyChanged("ToolboxItem");
350 void RaisePropertyChanged(string propertyName)
352 if (null != PropertyChanged)
354 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
358 void ValidateTool(Type toolType)
360 bool isInvalid = toolType.IsAbstract;
361 isInvalid |= toolType.IsInterface;
362 isInvalid |= !toolType.IsVisible;
363 ConstructorInfo ctor = toolType.GetConstructor(Type.EmptyTypes);
364 isInvalid |= (null == ctor);
367 string reason = string.Empty;
368 if (toolType.IsAbstract)
370 reason = "IsAbstract == true ";
372 if (toolType.IsInterface)
374 reason += "IsInterface == true ";
376 if (!toolType.IsVisible)
378 reason += "IsVisible == false ";
382 reason += SR.NoDefaultCtorError;
385 string error = string.Format(CultureInfo.CurrentCulture, SR.NotSupportedToolboxTypeFormatString, toolType.Name, reason);
386 throw FxTrace.Exception.AsError(new NotSupportedException(error));
390 public override string ToString()
392 return this.ToolName;
395 [DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
396 private static extern IntPtr GetDC(IntPtr hWnd);
398 [DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
399 private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
401 [DllImport("Gdi32.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
402 private static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
404 internal static int GetSystemDpi(int index)
406 IntPtr dc = GetDC(IntPtr.Zero);
407 //if dc is null, just return the common Dpi value
415 return GetDeviceCaps(dc, index);
419 ReleaseDC(IntPtr.Zero, dc);