e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
424 lines
16 KiB
C#
424 lines
16 KiB
C#
//------------------------------------------------------------------------------
|
|
// <copyright file="DesignerAdapterUtil.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
//------------------------------------------------------------------------------
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.ComponentModel;
|
|
using System.ComponentModel.Design;
|
|
using System.Drawing;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
using System.Web.UI.Design;
|
|
using System.Web.UI.Design.MobileControls;
|
|
using System.Web.UI.MobileControls;
|
|
using System.Web.UI.MobileControls.Adapters;
|
|
|
|
namespace System.Web.UI.Design.MobileControls.Adapters
|
|
{
|
|
[
|
|
System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand,
|
|
Flags=System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)
|
|
]
|
|
[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.")]
|
|
internal static class DesignerAdapterUtil
|
|
{
|
|
// margin width is 10px on right (10px on left taken care of by parentChildOffset)
|
|
private const int _marginWidth = 10;
|
|
// default Panel or Form width
|
|
private const int _defaultContainerWidth = 300;
|
|
// 11px on the left and the right for padding and margin between levels
|
|
private const int _marginPerLevel = 22;
|
|
// offset of control within a template is 10px on the left + 11px on the right + 1
|
|
private const int _templateParentChildOffset = 22;
|
|
// offset of control outside of a template is 11px
|
|
private const int _regularParentChildOffset = 11;
|
|
|
|
// default width for controls in templates. The value doesn't matter as long as it is
|
|
// equal or larger than parent width, since the parent control designer will still
|
|
// truncate to 100%
|
|
internal const int CONTROL_MAX_WIDTH_IN_TEMPLATE = 300;
|
|
internal const byte CONTROL_IN_TEMPLATE_NONEDIT = 0x01;
|
|
internal const byte CONTROL_IN_TEMPLATE_EDIT = 0x02;
|
|
|
|
internal static IDesigner ControlDesigner(IComponent component)
|
|
{
|
|
Debug.Assert(null != component);
|
|
ISite compSite = component.Site;
|
|
|
|
if (compSite != null)
|
|
{
|
|
return ((IDesignerHost) compSite.GetService(typeof(IDesignerHost))).GetDesigner(component);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
internal static ContainmentStatus GetContainmentStatus(Control control)
|
|
{
|
|
ContainmentStatus containmentStatus = ContainmentStatus.Unknown;
|
|
Control parent = control.Parent;
|
|
|
|
if (control == null || parent == null)
|
|
{
|
|
return containmentStatus;
|
|
}
|
|
|
|
if (parent is Form)
|
|
{
|
|
containmentStatus = ContainmentStatus.InForm;
|
|
}
|
|
else if (parent is Panel)
|
|
{
|
|
containmentStatus = ContainmentStatus.InPanel;
|
|
}
|
|
else if (parent is Page || parent is UserControl)
|
|
{
|
|
containmentStatus = ContainmentStatus.AtTopLevel;
|
|
}
|
|
else if (InTemplateFrame(control))
|
|
{
|
|
containmentStatus = ContainmentStatus.InTemplateFrame;
|
|
}
|
|
|
|
return containmentStatus;
|
|
}
|
|
|
|
internal static IComponent GetRootComponent(IComponent component)
|
|
{
|
|
Debug.Assert(null != component);
|
|
ISite compSite = component.Site;
|
|
|
|
if (compSite != null)
|
|
{
|
|
IDesignerHost host = (IDesignerHost)compSite.GetService(typeof(IDesignerHost));
|
|
if (host != null)
|
|
{
|
|
return host.RootComponent;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
internal static String GetWidth(Control control)
|
|
{
|
|
if (DesignerAdapterUtil.GetContainmentStatus(control) == ContainmentStatus.AtTopLevel)
|
|
{
|
|
return Constants.ControlSizeAtToplevelInNonErrorMode;
|
|
}
|
|
return Constants.ControlSizeInContainer;
|
|
}
|
|
|
|
internal static bool InMobilePage(Control control)
|
|
{
|
|
return (control != null && control.Page is MobilePage);
|
|
}
|
|
|
|
internal static bool InUserControl(IComponent component)
|
|
{
|
|
return GetRootComponent(component) is UserControl;
|
|
}
|
|
|
|
internal static bool InMobileUserControl(IComponent component)
|
|
{
|
|
return GetRootComponent(component) is MobileUserControl;
|
|
}
|
|
|
|
// Returns true if the closest templateable ancestor is in template editing mode.
|
|
internal static bool InTemplateFrame(Control control)
|
|
{
|
|
if (control.Parent == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
TemplatedControlDesigner designer =
|
|
ControlDesigner(control.Parent) as TemplatedControlDesigner;
|
|
|
|
if (designer == null)
|
|
{
|
|
return InTemplateFrame(control.Parent);
|
|
}
|
|
|
|
if (designer.InTemplateMode)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
internal static void AddAttributesToProperty(
|
|
Type designerType,
|
|
IDictionary properties,
|
|
String propertyName,
|
|
Attribute[] attributeArray)
|
|
{
|
|
Debug.Assert (propertyName != null &&
|
|
propertyName.Length != 0);
|
|
|
|
PropertyDescriptor prop = (PropertyDescriptor)properties[propertyName];
|
|
Debug.Assert(prop != null);
|
|
|
|
prop = TypeDescriptor.CreateProperty (
|
|
designerType,
|
|
prop,
|
|
attributeArray);
|
|
|
|
properties[propertyName] = prop;
|
|
}
|
|
|
|
internal static void AddAttributesToPropertiesOfDifferentType(
|
|
Type designerType,
|
|
Type newType,
|
|
IDictionary properties,
|
|
String propertyName,
|
|
Attribute newAttribute)
|
|
{
|
|
Debug.Assert (propertyName != null &&
|
|
propertyName.Length != 0);
|
|
|
|
PropertyDescriptor prop = (PropertyDescriptor)properties[propertyName];
|
|
Debug.Assert(prop != null);
|
|
|
|
// we can't create the designer DataSource property based on the runtime property since their
|
|
// types do not match. Therefore, we have to copy over all the attributes from the runtime
|
|
// and use them that way.
|
|
System.ComponentModel.AttributeCollection runtimeAttributes = prop.Attributes;
|
|
Attribute[] attrs = new Attribute[runtimeAttributes.Count + 1];
|
|
runtimeAttributes.CopyTo(attrs, 0);
|
|
|
|
attrs[runtimeAttributes.Count] = newAttribute;
|
|
prop = TypeDescriptor.CreateProperty (
|
|
designerType,
|
|
propertyName,
|
|
newType,
|
|
attrs);
|
|
|
|
properties[propertyName] = prop;
|
|
}
|
|
|
|
internal static int NestingLevel(Control control,
|
|
out bool inTemplate,
|
|
out int defaultControlWidthInTemplate)
|
|
{
|
|
int level = -1;
|
|
defaultControlWidthInTemplate = 0;
|
|
inTemplate = false;
|
|
if (control != null)
|
|
{
|
|
Control parent = control.Parent;
|
|
while (parent != null)
|
|
{
|
|
level++;
|
|
IDesigner designer = ControlDesigner(parent);
|
|
if (designer is MobileTemplatedControlDesigner)
|
|
{
|
|
defaultControlWidthInTemplate =
|
|
((MobileTemplatedControlDesigner) designer).TemplateWidth -
|
|
_templateParentChildOffset;
|
|
inTemplate = true;
|
|
return level;
|
|
}
|
|
parent = parent.Parent;
|
|
}
|
|
}
|
|
return level;
|
|
}
|
|
|
|
internal static void SetStandardStyleAttributes(IHtmlControlDesignerBehavior behavior,
|
|
ContainmentStatus containmentStatus)
|
|
{
|
|
if (behavior == null) {
|
|
return;
|
|
}
|
|
|
|
bool controlAtTopLevel = (containmentStatus == ContainmentStatus.AtTopLevel);
|
|
|
|
Color cw = SystemColors.Window;
|
|
Color ct = SystemColors.WindowText;
|
|
Color c = Color.FromArgb((Int16)(ct.R * 0.1 + cw.R * 0.9),
|
|
(Int16)(ct.G * 0.1 + cw.G * 0.9),
|
|
(Int16)(ct.B * 0.1 + cw.B * 0.9));
|
|
behavior.SetStyleAttribute("borderColor", true, ColorTranslator.ToHtml(c), true);
|
|
behavior.SetStyleAttribute("borderStyle", true, "solid", true);
|
|
|
|
behavior.SetStyleAttribute("borderWidth", true, "1px", true);
|
|
behavior.SetStyleAttribute("marginLeft", true, "5px", true);
|
|
behavior.SetStyleAttribute("marginRight", true, controlAtTopLevel ? "30%" : "5px", true);
|
|
behavior.SetStyleAttribute("marginTop", true, controlAtTopLevel ? "5px" : "2px", true);
|
|
behavior.SetStyleAttribute("marginBottom", true, controlAtTopLevel ? "5px" : "2px", true);
|
|
}
|
|
|
|
internal static String GetDesignTimeErrorHtml(
|
|
String errorMessage,
|
|
bool infoMode,
|
|
Control control,
|
|
IHtmlControlDesignerBehavior behavior,
|
|
ContainmentStatus containmentStatus)
|
|
{
|
|
String id = String.Empty;
|
|
Debug.Assert(control != null, "control is null");
|
|
|
|
if (control.Site != null)
|
|
{
|
|
id = control.Site.Name;
|
|
}
|
|
|
|
if (behavior != null) {
|
|
behavior.SetStyleAttribute("borderWidth", true, "0px", true);
|
|
}
|
|
|
|
return String.Format(CultureInfo.CurrentCulture,
|
|
MobileControlDesigner.defaultErrorDesignTimeHTML,
|
|
new Object[]
|
|
{
|
|
control.GetType().Name,
|
|
id,
|
|
errorMessage,
|
|
infoMode? MobileControlDesigner.infoIcon : MobileControlDesigner.errorIcon,
|
|
((containmentStatus == ContainmentStatus.AtTopLevel) ?
|
|
Constants.ControlSizeAtToplevelInErrormode :
|
|
Constants.ControlSizeInContainer)
|
|
});
|
|
}
|
|
|
|
internal static int GetMaxWidthToFit(MobileControl control, out byte templateStatus)
|
|
{
|
|
IDesigner parentDesigner = ControlDesigner(control.Parent);
|
|
IDesigner controlDesigner = ControlDesigner(control);
|
|
int defaultControlWidthInTemplate;
|
|
|
|
NativeMethods.IHTMLElement2 htmlElement2Parent = null;
|
|
|
|
if (controlDesigner == null)
|
|
{
|
|
templateStatus = CONTROL_IN_TEMPLATE_NONEDIT;
|
|
return 0;
|
|
}
|
|
Debug.Assert(controlDesigner is MobileControlDesigner ||
|
|
controlDesigner is MobileTemplatedControlDesigner,
|
|
"controlDesigner is not MobileControlDesigner or MobileTemplatedControlDesigner");
|
|
|
|
templateStatus = 0x00;
|
|
if (parentDesigner is MobileTemplatedControlDesigner)
|
|
{
|
|
htmlElement2Parent =
|
|
(NativeMethods.IHTMLElement2)
|
|
((MobileTemplatedControlDesigner) parentDesigner).DesignTimeElementInternal;
|
|
}
|
|
else if (parentDesigner is MobileContainerDesigner)
|
|
{
|
|
htmlElement2Parent =
|
|
(NativeMethods.IHTMLElement2)
|
|
((MobileContainerDesigner) parentDesigner).DesignTimeElementInternal;
|
|
}
|
|
|
|
bool inTemplate;
|
|
int nestingLevel = DesignerAdapterUtil.NestingLevel(control, out inTemplate, out defaultControlWidthInTemplate);
|
|
if (inTemplate)
|
|
{
|
|
templateStatus = CONTROL_IN_TEMPLATE_EDIT;
|
|
}
|
|
|
|
if (htmlElement2Parent != null)
|
|
{
|
|
int maxWidth;
|
|
if (!inTemplate)
|
|
{
|
|
Debug.Assert(control.Parent is MobileControl);
|
|
Style parentStyle = ((MobileControl) control.Parent).Style;
|
|
Alignment alignment = (Alignment) parentStyle[Style.AlignmentKey, true];
|
|
int parentChildOffset=0;
|
|
|
|
// AUI 2786
|
|
if (alignment != Alignment.NotSet && alignment != Alignment.Left)
|
|
{
|
|
parentChildOffset = _regularParentChildOffset;
|
|
}
|
|
else
|
|
{
|
|
NativeMethods.IHTMLRectCollection rectColl = null;
|
|
NativeMethods.IHTMLRect rect = null;
|
|
int index = 0;
|
|
Object obj = index;
|
|
|
|
NativeMethods.IHTMLElement2 htmlElement2;
|
|
|
|
if (controlDesigner is MobileControlDesigner)
|
|
{
|
|
htmlElement2 = (NativeMethods.IHTMLElement2) ((MobileControlDesigner) controlDesigner).DesignTimeElementInternal;
|
|
}
|
|
else
|
|
{
|
|
htmlElement2 = (NativeMethods.IHTMLElement2) ((MobileTemplatedControlDesigner) controlDesigner).DesignTimeElementInternal;
|
|
}
|
|
|
|
if (null == htmlElement2)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
try
|
|
{
|
|
rectColl = htmlElement2.GetClientRects();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// this happens when switching from Design view to HTML view
|
|
return 0;
|
|
}
|
|
|
|
if( rectColl.GetLength() >= 1)
|
|
{
|
|
rect = (NativeMethods.IHTMLRect)rectColl.Item(ref obj);
|
|
parentChildOffset = rect.GetLeft();
|
|
|
|
rectColl = htmlElement2Parent.GetClientRects();
|
|
//Debug.Assert(rectColl.GetLength() == 1);
|
|
rect = (NativeMethods.IHTMLRect) rectColl.Item(ref obj);
|
|
parentChildOffset -= rect.GetLeft();
|
|
}
|
|
}
|
|
|
|
maxWidth = GetLength(htmlElement2Parent) - _marginWidth - parentChildOffset;
|
|
if (maxWidth > 0 && maxWidth > _defaultContainerWidth - nestingLevel * _marginPerLevel)
|
|
{
|
|
maxWidth = _defaultContainerWidth - nestingLevel * _marginPerLevel;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int parentWidth = GetLength(htmlElement2Parent);
|
|
if (parentWidth == 0)
|
|
{
|
|
// AUI 4525
|
|
maxWidth = defaultControlWidthInTemplate;
|
|
}
|
|
else
|
|
{
|
|
maxWidth = parentWidth - _templateParentChildOffset;
|
|
}
|
|
|
|
if (maxWidth > 0 && maxWidth > defaultControlWidthInTemplate - nestingLevel * _marginPerLevel)
|
|
{
|
|
maxWidth = defaultControlWidthInTemplate - nestingLevel * _marginPerLevel;
|
|
}
|
|
}
|
|
return maxWidth;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
private static int GetLength(NativeMethods.IHTMLElement2 element) {
|
|
NativeMethods.IHTMLRectCollection rectColl = element.GetClientRects();
|
|
//Debug.Assert(rectColl.GetLength() == 1);
|
|
Object obj = rectColl.GetLength() - 1;
|
|
NativeMethods.IHTMLRect rect = (NativeMethods.IHTMLRect)rectColl.Item(ref obj);
|
|
return rect.GetRight() - rect.GetLeft();
|
|
}
|
|
}
|
|
}
|