AirScout/AeroWizard/AeroWizard/GenericDesigner.cs

779 wiersze
23 KiB
C#

using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms.Design;
using System.Windows.Forms.Design.Behavior;
namespace System.ComponentModel.Design
{
internal static class ComponentDesignerExtension
{
public const System.Reflection.BindingFlags AllInstBind = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance;
public static object EditValue(this ComponentDesigner designer, object objectToChange, string propName)
{
PropertyDescriptor prop = TypeDescriptor.GetProperties(objectToChange)[propName];
EditorServiceContext context = new EditorServiceContext(designer, prop);
var editor = prop.GetEditor(typeof(System.Drawing.Design.UITypeEditor)) as System.Drawing.Design.UITypeEditor;
object curVal = prop.GetValue(objectToChange);
object newVal = editor.EditValue(context, context, curVal);
if (newVal != curVal)
try { prop.SetValue(objectToChange, newVal); }
catch (CheckoutException) { }
return newVal;
}
public static List<DesignerActionItem> GetAllAttributedActionItems(this DesignerActionList actionList)
{
var fullAIList = new List<DesignerActionItem>();
foreach (var mbr in actionList.GetType().GetMethods(AllInstBind))
{
foreach (IActionGetItem attr in mbr.GetCustomAttributes(typeof(DesignerActionMethodAttribute), false))
{
if (mbr.ReturnType == typeof(void) && mbr.GetParameters().Length == 0)
fullAIList.Add(attr.GetItem(actionList, mbr));
else
throw new FormatException("DesignerActionMethodAttribute must be applied to a method returning void and having no parameters.");
}
}
foreach (var mbr in actionList.GetType().GetProperties(AllInstBind))
{
foreach (IActionGetItem attr in mbr.GetCustomAttributes(typeof(DesignerActionPropertyAttribute), false))
fullAIList.Add(attr.GetItem(actionList, mbr));
}
fullAIList.Sort(CompareItems);
return fullAIList;
}
public static DesignerVerbCollection GetAttributedVerbs(this ComponentDesigner designer)
{
var verbs = new DesignerVerbCollection();
foreach (var m in designer.GetType().GetMethods(AllInstBind))
{
foreach (DesignerVerbAttribute attr in m.GetCustomAttributes(typeof(DesignerVerbAttribute), true))
{
verbs.Add(attr.GetDesignerVerb(designer, m));
}
}
return verbs;
}
public static DesignerActionItemCollection GetFilteredActionItems(this DesignerActionList actionList, List<DesignerActionItem> fullAIList)
{
DesignerActionItemCollection col = new DesignerActionItemCollection();
fullAIList.ForEach(ai => { if (CheckCondition(actionList, ai)) { col.Add(ai); } });
// Add header items for displayed items
int i = 0; string cat = null;
while (i < col.Count)
{
string curCat = col[i].Category;
if (string.Compare(curCat, cat, true, Globalization.CultureInfo.CurrentCulture) != 0)
{
col.Insert(i++, new DesignerActionHeaderItem(curCat));
cat = curCat;
}
i++;
}
return col;
}
public static IDictionary<string, List<Attribute>> GetRedirectedProperties(this ComponentDesigner d)
{
var ret = new Dictionary<string, List<Attribute>>();
foreach (var prop in d.GetType().GetProperties(AllInstBind))
{
foreach (RedirectedDesignerPropertyAttribute attr in prop.GetCustomAttributes(typeof(RedirectedDesignerPropertyAttribute), false))
{
List<Attribute> attributes;
if (attr.ApplyOtherAttributes)
{
attributes = new List<Attribute>(Array.ConvertAll<object, Attribute>(prop.GetCustomAttributes(false), o => o as System.Attribute));
attributes.RemoveAll(a => a is RedirectedDesignerPropertyAttribute);
}
else
attributes = new List<Attribute>();
ret.Add(prop.Name, attributes);
}
}
return ret;
}
public static void RedirectRegisteredProperties(this ComponentDesigner d, System.Collections.IDictionary properties, IDictionary<string, List<Attribute>> redirectedProps)
{
foreach (var propName in redirectedProps.Keys)
{
PropertyDescriptor oldPropertyDescriptor = (PropertyDescriptor)properties[propName];
if (oldPropertyDescriptor != null)
{
List<Attribute> attributes = redirectedProps[propName];
properties[propName] = TypeDescriptor.CreateProperty(d.GetType(), oldPropertyDescriptor, attributes.ToArray());
}
}
}
[Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "d")]
public static void RemoveProperties(this ComponentDesigner d, System.Collections.IDictionary properties, IEnumerable<string> propertiesToRemove)
{
foreach (string p in propertiesToRemove)
if (properties.Contains(p))
properties.Remove(p);
}
public static void SetComponentProperty<T>(this ComponentDesigner d, string propName, T value)
{
PropertyDescriptor propDesc = TypeDescriptor.GetProperties(d.Component)[propName];
if (propDesc != null && propDesc.PropertyType == typeof(T) && !propDesc.IsReadOnly && propDesc.IsBrowsable)
propDesc.SetValue(d.Component, value);
}
public static System.Windows.Forms.DialogResult ShowDialog(this ComponentDesigner designer, System.Windows.Forms.Form dialog)
{
EditorServiceContext context = new EditorServiceContext(designer);
return context.ShowDialog(dialog);
}
private static bool CheckCondition(DesignerActionList actionList, DesignerActionItem ai)
{
if (ai.Properties["Condition"] != null)
{
var p = actionList.GetType().GetProperty((string)ai.Properties["Condition"], AllInstBind, null, typeof(bool), Type.EmptyTypes, null);
if (p != null)
return (bool)p.GetValue(actionList, null);
}
return true;
}
private static int CompareItems(DesignerActionItem a, DesignerActionItem b)
{
int c = string.Compare(a.Category ?? string.Empty, b.Category ?? string.Empty, true, Globalization.CultureInfo.CurrentCulture);
if (c != 0)
return c;
c = (int)a.Properties["Order"] - (int)b.Properties["Order"];
if (c != 0)
return c;
return string.Compare(a.DisplayName, b.DisplayName, true, Globalization.CultureInfo.CurrentCulture);
}
}
[System.AttributeUsage(System.AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
internal sealed class RedirectedDesignerPropertyAttribute : System.Attribute
{
public RedirectedDesignerPropertyAttribute() { ApplyOtherAttributes = true; }
public bool ApplyOtherAttributes { get; set; }
}
}
namespace System.Windows.Forms.Design
{
internal interface IActionGetItem
{
string Category { get; }
DesignerActionItem GetItem(DesignerActionList actions, Reflection.MemberInfo mbr);
}
[System.AttributeUsage(System.AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
internal sealed class DesignerActionMethodAttribute : System.Attribute, IActionGetItem
{
public DesignerActionMethodAttribute(string displayName, int displayOrder = 0)
{
DisplayName = displayName;
DisplayOrder = displayOrder;
}
public bool AllowAssociate { get; set; }
public string Category { get; set; }
public string Condition { get; set; }
public string Description { get; set; }
public string DisplayName { get; }
public int DisplayOrder { get; }
public bool IncludeAsDesignerVerb { get; set; }
DesignerActionItem IActionGetItem.GetItem(DesignerActionList actions, Reflection.MemberInfo mbr)
{
var ret = new DesignerActionMethodItem(actions, mbr.Name, DisplayName, Category, Description, IncludeAsDesignerVerb)
{ AllowAssociate = AllowAssociate };
if (!string.IsNullOrEmpty(Condition))
ret.Properties.Add("Condition", Condition);
ret.Properties.Add("Order", DisplayOrder);
return ret;
}
}
[System.AttributeUsage(System.AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
internal sealed class DesignerActionPropertyAttribute : System.Attribute, IActionGetItem
{
public DesignerActionPropertyAttribute(string displayName, int displayOrder = 0)
{
DisplayName = displayName;
DisplayOrder = displayOrder;
}
public bool AllowAssociate { get; set; }
public string Category { get; set; }
public string Condition { get; set; }
public string Description { get; set; }
public string DisplayName { get; }
public int DisplayOrder { get; }
DesignerActionItem IActionGetItem.GetItem(DesignerActionList actions, Reflection.MemberInfo mbr)
{
var ret = new DesignerActionPropertyItem(mbr.Name, DisplayName, Category, Description)
{ AllowAssociate = AllowAssociate };
if (!string.IsNullOrEmpty(Condition))
ret.Properties.Add("Condition", Condition);
ret.Properties.Add("Order", DisplayOrder);
return ret;
}
}
[System.AttributeUsage(System.AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
internal sealed class DesignerVerbAttribute : System.Attribute
{
private CommandID cmdId;
private string menuText;
public DesignerVerbAttribute(string menuText)
{
this.menuText = menuText;
}
public DesignerVerbAttribute(string menuText, Guid commandMenuGroup, int commandId)
{
this.menuText = menuText;
cmdId = new CommandID(commandMenuGroup, commandId);
}
internal DesignerVerb GetDesignerVerb(object obj, Reflection.MethodInfo mi)
{
EventHandler handler = (EventHandler)Delegate.CreateDelegate(typeof(EventHandler), obj, mi);
if (cmdId != null)
return new DesignerVerb(menuText, handler, cmdId);
return new DesignerVerb(menuText, handler);
}
}
internal class EditorServiceContext : IWindowsFormsEditorService, ITypeDescriptorContext, IServiceProvider
{
private IComponentChangeService _componentChangeSvc;
private ComponentDesigner _designer;
private PropertyDescriptor _targetProperty;
internal EditorServiceContext(ComponentDesigner designer)
{
_designer = designer;
}
internal EditorServiceContext(ComponentDesigner designer, PropertyDescriptor prop)
{
_designer = designer;
_targetProperty = prop;
if (prop == null)
{
prop = TypeDescriptor.GetDefaultProperty(designer.Component);
if ((prop != null) && typeof(System.Collections.ICollection).IsAssignableFrom(prop.PropertyType))
_targetProperty = prop;
}
}
internal EditorServiceContext(ComponentDesigner designer, PropertyDescriptor prop, string newVerbText)
: this(designer, prop)
{
_designer.Verbs.Add(new DesignerVerb(newVerbText, new EventHandler(OnEditItems)));
}
private T GetService<T>() => (T)((IServiceProvider)this).GetService(typeof(T));
private void OnEditItems(object sender, EventArgs e)
{
object component = _targetProperty.GetValue(_designer.Component);
if (component != null)
{
CollectionEditor editor = TypeDescriptor.GetEditor(component, typeof(System.Drawing.Design.UITypeEditor)) as CollectionEditor;
if (editor != null)
editor.EditValue(this, this, component);
}
}
void ITypeDescriptorContext.OnComponentChanged()
{
ChangeService.OnComponentChanged(_designer.Component, _targetProperty, null, null);
}
bool ITypeDescriptorContext.OnComponentChanging()
{
try
{
ChangeService.OnComponentChanging(_designer.Component, _targetProperty);
}
catch (CheckoutException exception)
{
if (exception != CheckoutException.Canceled)
throw;
return false;
}
return true;
}
object IServiceProvider.GetService(Type serviceType)
{
if ((serviceType == typeof(ITypeDescriptorContext)) || (serviceType == typeof(IWindowsFormsEditorService)))
return this;
if ((_designer.Component != null) && (_designer.Component.Site != null))
return _designer.Component.Site.GetService(serviceType);
return null;
}
void IWindowsFormsEditorService.CloseDropDown()
{
}
void IWindowsFormsEditorService.DropDownControl(Control control)
{
}
public DialogResult ShowDialog(Form dialog)
{
if (dialog == null)
throw new ArgumentNullException(nameof(dialog));
IUIService service = GetService<IUIService>();
if (service != null)
return service.ShowDialog(dialog);
return dialog.ShowDialog(_designer.Component as IWin32Window);
}
private IComponentChangeService ChangeService
{
get
{
if (_componentChangeSvc == null)
_componentChangeSvc = GetService<IComponentChangeService>();
return _componentChangeSvc;
}
}
IContainer ITypeDescriptorContext.Container
{
get
{
if (_designer.Component.Site != null)
return _designer.Component.Site.Container;
return null;
}
}
object ITypeDescriptorContext.Instance => _designer.Component;
PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor => _targetProperty;
}
internal abstract class RichBehavior<D> : Behavior.Behavior where D : ControlDesigner
{
public RichBehavior(D designer)
{
Designer = designer;
}
public D Designer { get; }
}
internal class RichComponentDesigner<C, A> : ComponentDesigner
where C : Component
where A : _BaseDesignerActionList
{
private A actions;
private Adorner adorner;
private IDictionary<string, List<Attribute>> redirectedProps;
private DesignerVerbCollection verbs;
public override DesignerActionListCollection ActionLists
{
get
{
if (actions == null)
actions = Activator.CreateInstance(typeof(A), this, Component) as A;
return new DesignerActionListCollection(new DesignerActionList[] { actions });
}
}
public BehaviorService BehaviorService { get; private set; }
public IComponentChangeService ComponentChangeService { get; private set; }
public new C Component => (C)base.Component;
public virtual GlyphCollection Glyphs => Adorner.Glyphs;
public ISelectionService SelectionService { get; private set; }
public override DesignerVerbCollection Verbs
{
get
{
if (verbs == null)
verbs = this.GetAttributedVerbs();
return verbs;
}
}
internal Adorner Adorner
{
get
{
if (adorner == null)
{
adorner = new Adorner();
BehaviorService.Adorners.Add(adorner);
}
return adorner;
}
}
protected virtual IEnumerable<string> PropertiesToRemove => new string[0];
public override void Initialize(IComponent component)
{
base.Initialize(component);
BehaviorService = GetService<BehaviorService>();
SelectionService = GetService<ISelectionService>();
if (SelectionService != null)
SelectionService.SelectionChanged += OnSelectionChanged;
ComponentChangeService = GetService<IComponentChangeService>();
if (ComponentChangeService != null)
ComponentChangeService.ComponentChanged += OnComponentChanged;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (BehaviorService != null & adorner != null)
BehaviorService.Adorners.Remove(adorner);
ISelectionService ss = SelectionService;
if (ss != null)
ss.SelectionChanged -= OnSelectionChanged;
IComponentChangeService cs = ComponentChangeService;
if (cs != null)
cs.ComponentChanged -= OnComponentChanged;
}
base.Dispose(disposing);
}
protected virtual S GetService<S>() where S : class => (S)GetService(typeof(S));
protected virtual void OnComponentChanged(object sender, ComponentChangedEventArgs e)
{
}
protected virtual void OnSelectionChanged(object sender, EventArgs e)
{
}
protected override void PreFilterProperties(System.Collections.IDictionary properties)
{
base.PreFilterProperties(properties);
// RedirectRegisteredProperties
if (redirectedProps == null)
redirectedProps = this.GetRedirectedProperties();
this.RedirectRegisteredProperties(properties, redirectedProps);
// Remove properties
this.RemoveProperties(properties, PropertiesToRemove);
}
}
internal class RichControlDesigner<C, A> : ControlDesigner
where C : Control
where A : _BaseDesignerActionList
{
private A actions;
private Adorner adorner;
private IDictionary<string, List<Attribute>> redirectedProps;
private DesignerVerbCollection verbs;
public override DesignerActionListCollection ActionLists
{
get
{
if (actions == null)
actions = Activator.CreateInstance(typeof(A), this, Component) as A;
return new DesignerActionListCollection(new DesignerActionList[] { actions });
}
}
public new BehaviorService BehaviorService => base.BehaviorService;
public IComponentChangeService ComponentChangeService { get; private set; }
public new C Control => (C)base.Control;
public virtual GlyphCollection Glyphs => Adorner.Glyphs;
public ISelectionService SelectionService { get; private set; }
public override DesignerVerbCollection Verbs
{
get
{
if (verbs == null)
verbs = this.GetAttributedVerbs();
return verbs;
}
}
internal Adorner Adorner
{
get
{
if (adorner == null)
{
adorner = new Adorner();
BehaviorService.Adorners.Add(adorner);
}
return adorner;
}
}
protected virtual IEnumerable<string> PropertiesToRemove => new string[0];
public override void Initialize(IComponent component)
{
base.Initialize(component);
SelectionService = GetService<ISelectionService>();
if (SelectionService != null)
SelectionService.SelectionChanged += OnSelectionChanged;
ComponentChangeService = GetService<IComponentChangeService>();
if (ComponentChangeService != null)
ComponentChangeService.ComponentChanged += OnComponentChanged;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (BehaviorService != null)
BehaviorService.Adorners.Remove(adorner);
ISelectionService ss = SelectionService;
if (ss != null)
ss.SelectionChanged -= OnSelectionChanged;
IComponentChangeService cs = ComponentChangeService;
if (cs != null)
cs.ComponentChanged -= OnComponentChanged;
}
base.Dispose(disposing);
}
protected virtual S GetService<S>() where S : class => (S)GetService(typeof(S));
protected virtual void OnComponentChanged(object sender, ComponentChangedEventArgs e)
{
}
protected virtual void OnSelectionChanged(object sender, EventArgs e)
{
}
protected override void PreFilterProperties(System.Collections.IDictionary properties)
{
base.PreFilterProperties(properties);
// RedirectRegisteredProperties
if (redirectedProps == null)
redirectedProps = this.GetRedirectedProperties();
this.RedirectRegisteredProperties(properties, redirectedProps);
// Remove properties
this.RemoveProperties(properties, PropertiesToRemove);
}
}
internal abstract class _BaseDesignerActionList : DesignerActionList
{
private List<DesignerActionItem> fullAIList;
public _BaseDesignerActionList(ComponentDesigner designer, IComponent component)
: base(component)
{
base.AutoShow = true;
ParentDesigner = designer;
}
public ComponentDesigner ParentDesigner { get; }
public override DesignerActionItemCollection GetSortedActionItems()
{
// Retrieve all attributed methods and properties
if (fullAIList == null)
fullAIList = this.GetAllAttributedActionItems();
// Filter for conditions and load
return this.GetFilteredActionItems(fullAIList);
}
protected T GetComponentProperty<T>(string propName)
{
var p = ComponentProp(propName, typeof(T));
if (p != null)
return (T)p.GetValue(Component, null);
return default(T);
}
protected void SetComponentProperty<T>(string propName, T value)
{
var p = ComponentProp(propName, typeof(T));
if (p != null)
p.SetValue(Component, value, null);
}
private Reflection.PropertyInfo ComponentProp(string propName, Type retType) => Component.GetType().GetProperty(propName, ComponentDesignerExtension.AllInstBind, null, retType, Type.EmptyTypes, null);
}
internal abstract class RichDesignerActionList<D, C> : _BaseDesignerActionList where D : ComponentDesigner where C : Component
{
public RichDesignerActionList(D designer, C component) : base(designer, component)
{
ParentDesigner = designer;
}
public new C Component => (C)base.Component;
public new D ParentDesigner { get; }
}
internal abstract class RichGlyph<D> : Glyph, IDisposable where D : ControlDesigner
{
public RichGlyph(D designer, Behavior.Behavior behavior)
: base(behavior)
{
Designer = designer;
}
public D Designer { get; }
public virtual void Dispose()
{
}
public void SetBehavior(RichBehavior<D> b) { base.SetBehavior(b); }
}
internal class RichParentControlDesigner<C, A> : ParentControlDesigner
where C : Control
where A : _BaseDesignerActionList
{
private A actions;
private Adorner adorner;
private IDictionary<string, List<Attribute>> redirectedProps;
private DesignerVerbCollection verbs;
public override DesignerActionListCollection ActionLists
{
get
{
if (actions == null)
actions = Activator.CreateInstance(typeof(A), this, Component) as A;
return new DesignerActionListCollection(new DesignerActionList[] { actions });
}
}
public new BehaviorService BehaviorService => base.BehaviorService;
public IComponentChangeService ComponentChangeService { get; private set; }
public new C Control => (C)base.Control;
public virtual GlyphCollection Glyphs => Adorner.Glyphs;
public ISelectionService SelectionService { get; private set; }
public override DesignerVerbCollection Verbs
{
get
{
if (verbs == null)
verbs = this.GetAttributedVerbs();
return verbs;
}
}
internal Adorner Adorner
{
get
{
if (adorner == null)
{
adorner = new Adorner();
BehaviorService.Adorners.Add(adorner);
}
return adorner;
}
}
protected virtual IEnumerable<string> PropertiesToRemove => new string[0];
public override void Initialize(IComponent component)
{
base.Initialize(component);
SelectionService = GetService<ISelectionService>();
if (SelectionService != null)
SelectionService.SelectionChanged += OnSelectionChanged;
ComponentChangeService = GetService<IComponentChangeService>();
if (ComponentChangeService != null)
ComponentChangeService.ComponentChanged += OnComponentChanged;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (BehaviorService != null & adorner != null)
BehaviorService.Adorners.Remove(adorner);
ISelectionService ss = SelectionService;
if (ss != null)
ss.SelectionChanged -= OnSelectionChanged;
IComponentChangeService cs = ComponentChangeService;
if (cs != null)
cs.ComponentChanged -= OnComponentChanged;
}
base.Dispose(disposing);
}
protected virtual S GetService<S>() where S : class => (S)GetService(typeof(S));
protected virtual void OnComponentChanged(object sender, ComponentChangedEventArgs e)
{
}
protected virtual void OnSelectionChanged(object sender, EventArgs e)
{
}
protected override void PreFilterProperties(System.Collections.IDictionary properties)
{
base.PreFilterProperties(properties);
// RedirectRegisteredProperties
if (redirectedProps == null)
redirectedProps = this.GetRedirectedProperties();
this.RedirectRegisteredProperties(properties, redirectedProps);
// Remove properties
this.RemoveProperties(properties, PropertiesToRemove);
}
}
}