From 33164d3cb5503519d78152e7411219f290fc1567 Mon Sep 17 00:00:00 2001 From: Alexey Yakovlev Date: Sun, 22 Apr 2012 23:02:14 +0400 Subject: [PATCH] Added IronyTextBox control, a wrapper for FCTB with Irony parser support. --- Irony.WinForms/035.Irony.WinForms.2010.csproj | 12 ++ Irony.WinForms/BorderStyleEx.cs | 29 ++++ .../FastColoredTextBox/FastColoredTextBox.cs | 6 +- Irony.WinForms/IronyTextBox.Designer.cs | 55 ++++++++ Irony.WinForms/IronyTextBox.cs | 113 ++++++++++++++++ Irony.WinForms/IronyTextBox.resx | 120 ++++++++++++++++ Irony.WinForms/Proxies/DuckTypingProxy.cs | 128 ++++++++++++++++++ Irony.WinForms/Proxies/TextBoxProxy.cs | 29 ++++ 8 files changed, 488 insertions(+), 4 deletions(-) create mode 100644 Irony.WinForms/BorderStyleEx.cs create mode 100644 Irony.WinForms/IronyTextBox.Designer.cs create mode 100644 Irony.WinForms/IronyTextBox.cs create mode 100644 Irony.WinForms/IronyTextBox.resx create mode 100644 Irony.WinForms/Proxies/DuckTypingProxy.cs create mode 100644 Irony.WinForms/Proxies/TextBoxProxy.cs diff --git a/Irony.WinForms/035.Irony.WinForms.2010.csproj b/Irony.WinForms/035.Irony.WinForms.2010.csproj index 7546ad2..cf29963 100644 --- a/Irony.WinForms/035.Irony.WinForms.2010.csproj +++ b/Irony.WinForms/035.Irony.WinForms.2010.csproj @@ -43,6 +43,7 @@ + Form @@ -96,7 +97,15 @@ + + UserControl + + + IronyTextBox.cs + + + @@ -123,6 +132,9 @@ ReplaceForm.cs + + IronyTextBox.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Irony.WinForms/Proxies/DuckTypingProxy.cs b/Irony.WinForms/Proxies/DuckTypingProxy.cs new file mode 100644 index 0000000..e6d0f96 --- /dev/null +++ b/Irony.WinForms/Proxies/DuckTypingProxy.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.Remoting.Proxies; +using System.Reflection; +using System.Runtime.Remoting.Messaging; + +namespace Irony.WinForms.Proxies { + /// + /// Proxy class implementing duck typing semantics of the target object. + /// + /// Proxied type. + public class DuckTypingProxy : RealProxy { + /// + /// Initializes a new instance of the class. + /// + /// The target instance. + /// if set to true, all methods of type T are required to be supported by target. + public DuckTypingProxy(object target, bool strict = false) + : base(typeof(T)) { + Target = target; + Strict = strict; + BuildMethodTable(); + } + + /// + /// Gets the target instance. + /// + public object Target { get; private set; } + + /// + /// Gets a value indicating whether this supports all methods of type T. + /// + public bool Strict { get; private set; } + + private Dictionary ProxyMethods = new Dictionary(); + + private Dictionary TargetMethods = new Dictionary(); + + private BindingFlags Flags = BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.Public; + + private void BuildMethodTable() { + var targetType = Target.GetType(); + var proxyType = GetType(); + var methods = typeof(T).GetMethods(Flags); + var proxyFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly; + + foreach (var method in methods) { + // first, look for proxy method with the same signature + var parameters = method.GetParameters().Select(p => p.ParameterType).ToArray(); + var foundMethod = proxyType.GetMethod(method.Name, proxyFlags, null, parameters, null); + if (foundMethod != null) { + ProxyMethods[method.ToString()] = foundMethod; + continue; + } + + // next, look for target method with the same signature + foundMethod = targetType.GetMethod(method.Name, Flags, null, parameters, null); + if (foundMethod != null) { + TargetMethods[method.ToString()] = foundMethod; + continue; + } + + if (Strict) { + throw new MissingMethodException(method.Name); + } + } + } + + /// + /// Invokes the specified remoting message. + /// + /// The message to invoke. + public override IMessage Invoke(IMessage message) { + // note: we don't support constructor calls + var mcm = (IMethodCallMessage)message; + var minfo = (MethodInfo)mcm.MethodBase; + return InvokeMessage(mcm, minfo); + } + + private ReturnMessage InvokeMessage(IMethodCallMessage mcm, MethodInfo minfo) { + try { + object target = this; + MethodInfo method = null; + string key = minfo.ToString(); + + if (!ProxyMethods.TryGetValue(key, out method)) { + target = Target; + if (!TargetMethods.TryGetValue(key, out method)) { + throw new MissingMethodException(minfo.ToString()); + } + } + + var result = InvokeMethod(method, target, mcm.Args); + return new ReturnMessage(result, null, 0, null, mcm); + } catch (Exception ex) { + return new ReturnMessage(ex, mcm); + } + } + + /// + /// Invokes the specified method on the specified target instance. + /// + /// The method to invoke. + /// The target instance. + /// The arguments to pass. + /// Method return value. + protected virtual object InvokeMethod(MethodInfo method, object target, object[] arguments) { + return method.Invoke(target, arguments); + } + + /// + /// Sets the strong-typed proxy instance. + /// + public T Instance { + get { return (T)GetTransparentProxy(); } + } + + /// + /// Converts the specified proxy to the target type implicitly. + /// + /// The proxy to convert. + public static implicit operator T(DuckTypingProxy proxy) { + return proxy.Instance; + } + } +} diff --git a/Irony.WinForms/Proxies/TextBoxProxy.cs b/Irony.WinForms/Proxies/TextBoxProxy.cs new file mode 100644 index 0000000..7002c89 --- /dev/null +++ b/Irony.WinForms/Proxies/TextBoxProxy.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using System.Reflection; +using FastColoredTextBoxNS; + +namespace Irony.WinForms.Proxies { + /// + /// Proxy class to convert instance to a standard . + /// + public class TextBoxProxy : DuckTypingProxy { + /// + /// Initializes a new instance of the class. + /// + public TextBoxProxy(FastColoredTextBox textBox) : base(textBox) { + TextBox = textBox; + } + + private FastColoredTextBox TextBox { get; set; } + + protected override object InvokeMethod(MethodInfo method, object target, object[] arguments) { + var result = base.InvokeMethod(method, target, arguments); + TextBox.Invalidate(); + return result; + } + } +}