1 //------------------------------------------------------------------------------
2 // <copyright file="DesignerAdapterUtil.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6 
7 using System;
8 using System.Collections;
9 using System.ComponentModel;
10 using System.ComponentModel.Design;
11 using System.Drawing;
12 using System.Diagnostics;
13 using System.Globalization;
14 using System.Web.UI.Design;
15 using System.Web.UI.Design.MobileControls;
16 using System.Web.UI.MobileControls;
17 using System.Web.UI.MobileControls.Adapters;
18 
19 namespace System.Web.UI.Design.MobileControls.Adapters
20 {
21     [
22         System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand,
23         Flags=System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)
24     ]
25     [Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
26     internal static class DesignerAdapterUtil
27     {
28         // margin width is 10px on right (10px on left taken care of by parentChildOffset)
29         private const int _marginWidth = 10;
30         // default Panel or Form width
31         private const int _defaultContainerWidth = 300;
32         // 11px on the left and the right for padding and margin between levels
33         private const int _marginPerLevel = 22;
34         // offset of control within a template is 10px on the left + 11px on the right + 1
35         private const int _templateParentChildOffset = 22;
36         // offset of control outside of a template is 11px
37         private const int _regularParentChildOffset = 11;
38 
39         // default width for controls in templates. The value doesn't matter as long as it is
40         // equal or larger than parent width, since the parent control designer will still
41         // truncate to 100%
42         internal const int CONTROL_MAX_WIDTH_IN_TEMPLATE = 300;
43         internal const byte CONTROL_IN_TEMPLATE_NONEDIT = 0x01;
44         internal const byte CONTROL_IN_TEMPLATE_EDIT    = 0x02;
45 
ControlDesigner(IComponent component)46         internal static IDesigner ControlDesigner(IComponent component)
47         {
48             Debug.Assert(null != component);
49             ISite compSite = component.Site;
50 
51             if (compSite != null)
52             {
53                 return ((IDesignerHost) compSite.GetService(typeof(IDesignerHost))).GetDesigner(component);
54             }
55             return null;
56         }
57 
GetContainmentStatus(Control control)58         internal static ContainmentStatus GetContainmentStatus(Control control)
59         {
60             ContainmentStatus containmentStatus = ContainmentStatus.Unknown;
61             Control parent = control.Parent;
62 
63             if (control == null || parent == null)
64             {
65                 return containmentStatus;
66             }
67 
68             if (parent is Form)
69             {
70                 containmentStatus = ContainmentStatus.InForm;
71             }
72             else if (parent is Panel)
73             {
74                 containmentStatus = ContainmentStatus.InPanel;
75             }
76             else if (parent is Page || parent is UserControl)
77             {
78                 containmentStatus = ContainmentStatus.AtTopLevel;
79             }
80             else if (InTemplateFrame(control))
81             {
82                 containmentStatus = ContainmentStatus.InTemplateFrame;
83             }
84 
85             return containmentStatus;
86         }
87 
GetRootComponent(IComponent component)88         internal static IComponent GetRootComponent(IComponent component)
89         {
90             Debug.Assert(null != component);
91             ISite compSite = component.Site;
92 
93             if (compSite != null)
94             {
95                 IDesignerHost host = (IDesignerHost)compSite.GetService(typeof(IDesignerHost));
96                 if (host != null)
97                 {
98                     return host.RootComponent;
99                 }
100             }
101 
102             return null;
103         }
104 
GetWidth(Control control)105         internal static String GetWidth(Control control)
106         {
107             if (DesignerAdapterUtil.GetContainmentStatus(control) == ContainmentStatus.AtTopLevel)
108             {
109                 return Constants.ControlSizeAtToplevelInNonErrorMode;
110             }
111             return Constants.ControlSizeInContainer;
112         }
113 
InMobilePage(Control control)114         internal static bool InMobilePage(Control control)
115         {
116             return (control != null && control.Page is MobilePage);
117         }
118 
InUserControl(IComponent component)119         internal static bool InUserControl(IComponent component)
120         {
121             return GetRootComponent(component) is UserControl;
122         }
123 
InMobileUserControl(IComponent component)124         internal static bool InMobileUserControl(IComponent component)
125         {
126             return GetRootComponent(component) is MobileUserControl;
127         }
128 
129         // Returns true if the closest templateable ancestor is in template editing mode.
InTemplateFrame(Control control)130         internal static  bool InTemplateFrame(Control control)
131         {
132             if (control.Parent == null)
133             {
134                 return false;
135             }
136 
137             TemplatedControlDesigner designer =
138                 ControlDesigner(control.Parent) as TemplatedControlDesigner;
139 
140             if (designer == null)
141             {
142                 return InTemplateFrame(control.Parent);
143             }
144 
145             if (designer.InTemplateMode)
146             {
147                 return true;
148             }
149 
150             return false;
151         }
152 
AddAttributesToProperty( Type designerType, IDictionary properties, String propertyName, Attribute[] attributeArray)153         internal static  void AddAttributesToProperty(
154             Type designerType,
155             IDictionary properties,
156             String propertyName,
157             Attribute[] attributeArray)
158         {
159             Debug.Assert (propertyName != null &&
160                 propertyName.Length != 0);
161 
162             PropertyDescriptor prop = (PropertyDescriptor)properties[propertyName];
163             Debug.Assert(prop != null);
164 
165             prop = TypeDescriptor.CreateProperty (
166                 designerType,
167                 prop,
168                 attributeArray);
169 
170             properties[propertyName] = prop;
171         }
172 
AddAttributesToPropertiesOfDifferentType( Type designerType, Type newType, IDictionary properties, String propertyName, Attribute newAttribute)173         internal static  void AddAttributesToPropertiesOfDifferentType(
174             Type designerType,
175             Type newType,
176             IDictionary properties,
177             String propertyName,
178             Attribute newAttribute)
179         {
180             Debug.Assert (propertyName != null &&
181                 propertyName.Length != 0);
182 
183             PropertyDescriptor prop = (PropertyDescriptor)properties[propertyName];
184             Debug.Assert(prop != null);
185 
186             // we can't create the designer DataSource property based on the runtime property since their
187             // types do not match. Therefore, we have to copy over all the attributes from the runtime
188             // and use them that way.
189             System.ComponentModel.AttributeCollection runtimeAttributes = prop.Attributes;
190             Attribute[] attrs = new Attribute[runtimeAttributes.Count + 1];
191             runtimeAttributes.CopyTo(attrs, 0);
192 
193             attrs[runtimeAttributes.Count] = newAttribute;
194             prop = TypeDescriptor.CreateProperty (
195                 designerType,
196                 propertyName,
197                 newType,
198                 attrs);
199 
200             properties[propertyName] = prop;
201         }
202 
NestingLevel(Control control, out bool inTemplate, out int defaultControlWidthInTemplate)203         internal static  int NestingLevel(Control control,
204                                        out bool inTemplate,
205                                        out int defaultControlWidthInTemplate)
206         {
207             int level = -1;
208             defaultControlWidthInTemplate = 0;
209             inTemplate = false;
210             if (control != null)
211             {
212                 Control parent = control.Parent;
213                 while (parent != null)
214                 {
215                     level++;
216                     IDesigner designer = ControlDesigner(parent);
217                     if (designer is MobileTemplatedControlDesigner)
218                     {
219                         defaultControlWidthInTemplate =
220                             ((MobileTemplatedControlDesigner) designer).TemplateWidth -
221                             _templateParentChildOffset;
222                         inTemplate = true;
223                         return level;
224                     }
225                     parent = parent.Parent;
226                 }
227             }
228             return level;
229         }
230 
SetStandardStyleAttributes(IHtmlControlDesignerBehavior behavior, ContainmentStatus containmentStatus)231         internal static  void SetStandardStyleAttributes(IHtmlControlDesignerBehavior behavior,
232                                                       ContainmentStatus containmentStatus)
233         {
234             if (behavior == null) {
235                 return;
236             }
237 
238             bool controlAtTopLevel = (containmentStatus == ContainmentStatus.AtTopLevel);
239 
240             Color cw = SystemColors.Window;
241             Color ct = SystemColors.WindowText;
242             Color c = Color.FromArgb((Int16)(ct.R * 0.1 + cw.R * 0.9),
243                 (Int16)(ct.G * 0.1 + cw.G * 0.9),
244                 (Int16)(ct.B * 0.1 + cw.B * 0.9));
245             behavior.SetStyleAttribute("borderColor", true, ColorTranslator.ToHtml(c), true);
246             behavior.SetStyleAttribute("borderStyle", true, "solid", true);
247 
248             behavior.SetStyleAttribute("borderWidth", true, "1px", true);
249             behavior.SetStyleAttribute("marginLeft", true, "5px", true);
250             behavior.SetStyleAttribute("marginRight", true, controlAtTopLevel ? "30%" : "5px", true);
251             behavior.SetStyleAttribute("marginTop", true, controlAtTopLevel ? "5px" : "2px", true);
252             behavior.SetStyleAttribute("marginBottom", true, controlAtTopLevel ? "5px" : "2px", true);
253         }
254 
GetDesignTimeErrorHtml( String errorMessage, bool infoMode, Control control, IHtmlControlDesignerBehavior behavior, ContainmentStatus containmentStatus)255         internal static  String GetDesignTimeErrorHtml(
256             String errorMessage,
257             bool infoMode,
258             Control control,
259             IHtmlControlDesignerBehavior behavior,
260             ContainmentStatus containmentStatus)
261         {
262             String id = String.Empty;
263             Debug.Assert(control != null, "control is null");
264 
265             if (control.Site != null)
266             {
267                 id = control.Site.Name;
268             }
269 
270             if (behavior != null) {
271                 behavior.SetStyleAttribute("borderWidth", true, "0px", true);
272             }
273 
274             return String.Format(CultureInfo.CurrentCulture,
275                 MobileControlDesigner.defaultErrorDesignTimeHTML,
276                 new Object[]
277                 {
278                     control.GetType().Name,
279                     id,
280                     errorMessage,
281                     infoMode? MobileControlDesigner.infoIcon : MobileControlDesigner.errorIcon,
282                     ((containmentStatus == ContainmentStatus.AtTopLevel) ?
283                     Constants.ControlSizeAtToplevelInErrormode :
284                     Constants.ControlSizeInContainer)
285                 });
286         }
287 
GetMaxWidthToFit(MobileControl control, out byte templateStatus)288         internal static  int GetMaxWidthToFit(MobileControl control, out byte templateStatus)
289         {
290             IDesigner parentDesigner = ControlDesigner(control.Parent);
291             IDesigner controlDesigner = ControlDesigner(control);
292             int defaultControlWidthInTemplate;
293 
294             NativeMethods.IHTMLElement2 htmlElement2Parent = null;
295 
296             if (controlDesigner == null)
297             {
298                 templateStatus = CONTROL_IN_TEMPLATE_NONEDIT;
299                 return 0;
300             }
301             Debug.Assert(controlDesigner is MobileControlDesigner ||
302                          controlDesigner is MobileTemplatedControlDesigner,
303                          "controlDesigner is not MobileControlDesigner or MobileTemplatedControlDesigner");
304 
305             templateStatus = 0x00;
306             if (parentDesigner is MobileTemplatedControlDesigner)
307             {
308                 htmlElement2Parent =
309                     (NativeMethods.IHTMLElement2)
310                     ((MobileTemplatedControlDesigner) parentDesigner).DesignTimeElementInternal;
311             }
312             else if (parentDesigner is MobileContainerDesigner)
313             {
314                 htmlElement2Parent =
315                     (NativeMethods.IHTMLElement2)
316                     ((MobileContainerDesigner) parentDesigner).DesignTimeElementInternal;
317             }
318 
319             bool inTemplate;
320             int nestingLevel = DesignerAdapterUtil.NestingLevel(control, out inTemplate, out defaultControlWidthInTemplate);
321             if (inTemplate)
322             {
323                 templateStatus = CONTROL_IN_TEMPLATE_EDIT;
324             }
325 
326             if (htmlElement2Parent != null)
327             {
328                 int maxWidth;
329                 if (!inTemplate)
330                 {
331                     Debug.Assert(control.Parent is MobileControl);
332                     Style parentStyle = ((MobileControl) control.Parent).Style;
333                     Alignment alignment = (Alignment) parentStyle[Style.AlignmentKey, true];
334                     int parentChildOffset=0;
335 
336                     // AUI 2786
337                     if (alignment != Alignment.NotSet && alignment != Alignment.Left)
338                     {
339                         parentChildOffset = _regularParentChildOffset;
340                     }
341                     else
342                     {
343                         NativeMethods.IHTMLRectCollection rectColl = null;
344                         NativeMethods.IHTMLRect rect = null;
345                         int index = 0;
346                         Object obj = index;
347 
348                         NativeMethods.IHTMLElement2 htmlElement2;
349 
350                         if (controlDesigner is MobileControlDesigner)
351                         {
352                             htmlElement2 = (NativeMethods.IHTMLElement2) ((MobileControlDesigner) controlDesigner).DesignTimeElementInternal;
353                         }
354                         else
355                         {
356                             htmlElement2 = (NativeMethods.IHTMLElement2) ((MobileTemplatedControlDesigner) controlDesigner).DesignTimeElementInternal;
357                         }
358 
359                         if (null == htmlElement2)
360                         {
361                             return 0;
362                         }
363 
364                         try
365                         {
366                             rectColl = htmlElement2.GetClientRects();
367                         }
368                         catch (Exception)
369                         {
370                             // this happens when switching from Design view to HTML view
371                             return 0;
372                         }
373 
374                         if( rectColl.GetLength() >= 1)
375                         {
376                             rect = (NativeMethods.IHTMLRect)rectColl.Item(ref obj);
377                             parentChildOffset = rect.GetLeft();
378 
379                             rectColl = htmlElement2Parent.GetClientRects();
380                             //Debug.Assert(rectColl.GetLength() == 1);
381                             rect = (NativeMethods.IHTMLRect) rectColl.Item(ref obj);
382                             parentChildOffset -= rect.GetLeft();
383                         }
384                     }
385 
386                     maxWidth = GetLength(htmlElement2Parent) - _marginWidth - parentChildOffset;
387                     if (maxWidth > 0 && maxWidth > _defaultContainerWidth - nestingLevel * _marginPerLevel)
388                     {
389                         maxWidth = _defaultContainerWidth - nestingLevel * _marginPerLevel;
390                     }
391                 }
392                 else
393                 {
394                     int parentWidth = GetLength(htmlElement2Parent);
395                     if (parentWidth == 0)
396                     {
397                         // AUI 4525
398                         maxWidth = defaultControlWidthInTemplate;
399                     }
400                     else
401                     {
402                         maxWidth = parentWidth - _templateParentChildOffset;
403                     }
404 
405                     if (maxWidth > 0 && maxWidth > defaultControlWidthInTemplate - nestingLevel * _marginPerLevel)
406                     {
407                         maxWidth = defaultControlWidthInTemplate - nestingLevel * _marginPerLevel;
408                     }
409                 }
410                 return maxWidth;
411             }
412             return 0;
413         }
414 
GetLength(NativeMethods.IHTMLElement2 element)415         private static int GetLength(NativeMethods.IHTMLElement2 element) {
416             NativeMethods.IHTMLRectCollection rectColl = element.GetClientRects();
417             //Debug.Assert(rectColl.GetLength() == 1);
418             Object obj = rectColl.GetLength() - 1;
419             NativeMethods.IHTMLRect rect = (NativeMethods.IHTMLRect)rectColl.Item(ref obj);
420             return rect.GetRight() - rect.GetLeft();
421         }
422     }
423 }
424