diff options
| author | jpbruyere <jp.bruyere@hotmail.com> | 2015-05-18 18:13:48 +0200 |
|---|---|---|
| committer | jpbruyere <jp.bruyere@hotmail.com> | 2015-05-18 18:13:48 +0200 |
| commit | fd19c1fd6960faf9b7131a4dfade4bba95abcf81 (patch) | |
| tree | 59653a3db212e877aa125884e85e11333bc474cd /src | |
| parent | 2a48f25993b48535eb84f0e83e4dd7c064ed6e49 (diff) | |
Simple bindings
demonstration in testFps
Diffstat (limited to 'src')
| -rw-r--r-- | src/CompilerServices/CompilerServices.cs | 112 | ||||
| -rwxr-xr-x | src/DynAttribute.cs (renamed from src/EventSource.cs) | 6 | ||||
| -rw-r--r-- | src/GraphicObjects/Checkbox.cs | 6 | ||||
| -rw-r--r-- | src/GraphicObjects/GraphicObject.cs | 20 | ||||
| -rw-r--r-- | src/GraphicObjects/Group.cs | 5 | ||||
| -rw-r--r-- | src/GraphicObjects/IValueChange.cs | 30 | ||||
| -rwxr-xr-x | src/GraphicObjects/Image.cs | 1 | ||||
| -rw-r--r-- | src/GraphicObjects/NumericControl.cs | 46 | ||||
| -rw-r--r-- | src/GraphicObjects/Spinner.cs | 43 | ||||
| -rw-r--r-- | src/GraphicObjects/TextBox.cs | 31 | ||||
| -rw-r--r-- | src/Interface.cs | 50 | ||||
| -rw-r--r-- | src/TextChangeEventArgs.cs | 9 |
12 files changed, 271 insertions, 88 deletions
diff --git a/src/CompilerServices/CompilerServices.cs b/src/CompilerServices/CompilerServices.cs index 034180d1..36c88030 100644 --- a/src/CompilerServices/CompilerServices.cs +++ b/src/CompilerServices/CompilerServices.cs @@ -1,6 +1,10 @@ using System; using System.Reflection.Emit; using System.Reflection; +using System.Collections; +using System.Diagnostics; +using System.Linq; + namespace go { @@ -33,12 +37,12 @@ namespace go } static int dynHandleCpt = 0; - public static void CompileEventSource(EventSource es) + public static void CompileEventSource(DynAttribute es) { Type srcType = es.Source.GetType (); #region Retrieve EventHandler parameter type - EventInfo ei = srcType.GetEvent (es.EventName); + EventInfo ei = srcType.GetEvent (es.MemberName); MethodInfo invoke = ei.EventHandlerType.GetMethod ("Invoke"); ParameterInfo[] pars = invoke.GetParameters (); @@ -54,10 +58,10 @@ namespace go #region IL generation ILGenerator il = dm.GetILGenerator(256); - string src = es.Handler.Trim(); + string src = es.Value.Trim(); if (! (src.StartsWith("{") || src.EndsWith ("}"))) - throw new Exception (string.Format("GOML:Malformed {0} Event handler: {1}", es.EventName, es.Handler)); + throw new Exception (string.Format("GOML:Malformed {0} Event handler: {1}", es.MemberName, es.Value)); src = src.Substring (1, src.Length - 2); string[] srcLines = src.Split (new char[] { ';' }); @@ -145,11 +149,109 @@ namespace go #endregion - FieldInfo evtFi = getEventHandlerField (srcType, es.EventName); + FieldInfo evtFi = getEventHandlerField (srcType, es.MemberName); Delegate del = dm.CreateDelegate(evtFi.FieldType); evtFi.SetValue(es.Source, del); } + public static void CreateBinding(DynAttribute binding, object _source) + { + + Type srcType = _source.GetType (); + Type dstType = binding.Source.GetType (); + + MemberInfo miSrc = srcType.GetMember (binding.Value).FirstOrDefault(); + Type srcValueType = null; + if (miSrc.MemberType == MemberTypes.Property) + srcValueType = (miSrc as PropertyInfo).PropertyType; + else if (miSrc.MemberType == MemberTypes.Field) + srcValueType = (miSrc as FieldInfo).FieldType; + else + throw new Exception("unandled source type for binding"); + + #region Retrieve EventHandler parameter type + EventInfo ei = srcType.GetEvent ("ValueChanged"); + MethodInfo evtInvoke = ei.EventHandlerType.GetMethod ("Invoke"); + ParameterInfo[] evtParams = evtInvoke.GetParameters (); + + Type handlerArgsType = evtParams [1].ParameterType; + #endregion + + Type[] args = {typeof(object), handlerArgsType}; + DynamicMethod dm = new DynamicMethod("dynHandle_" + dynHandleCpt, + typeof(void), + args, + srcType.Module, true); + + //register target object reference + int dstIdx = Interface.References.IndexOf(binding.Source); + + if (dstIdx < 0) { + dstIdx = Interface.References.Count; + Interface.References.Add (binding.Source); + } + + + + #region IL generation + ILGenerator il = dm.GetILGenerator(256); + + System.Reflection.Emit.Label labFailed = il.DefineLabel(); + System.Reflection.Emit.Label labContinue = il.DefineLabel(); + + #region test if valueChange event is the correct one + il.Emit (OpCodes.Ldstr, binding.Value); + //push name from arg + il.Emit(OpCodes.Ldarg_1); + FieldInfo fiMbName = typeof(ValueChangeEventArgs).GetField("MemberName"); + il.Emit(OpCodes.Ldfld, fiMbName); + MethodInfo miStrEqu = typeof(string).GetMethod("op_Inequality", new Type[] {typeof(string),typeof(string)}); + il.Emit(OpCodes.Call, miStrEqu); + il.Emit(OpCodes.Brfalse_S, labContinue); + il.Emit(OpCodes.Br_S, labFailed); + il.MarkLabel(labContinue); + #endregion + + string[] srcLines = binding.Value.Trim().Split (new char[] { ';' }); + foreach (string srcLine in srcLines) { + MethodInfo infoWriteLine = typeof(System.Diagnostics.Debug).GetMethod("WriteLine", new Type[] { typeof(string) }); + + string statement = srcLine.Trim (); + + //load target ref onto the stack + FieldInfo fiRefs = typeof(Interface).GetField("References"); + il.Emit(OpCodes.Ldsfld, fiRefs); + il.Emit(OpCodes.Ldc_I4, dstIdx); + + MethodInfo miGetRef = Interface.References.GetType().GetMethod("get_Item"); + il.Emit(OpCodes.Callvirt, miGetRef); + il.Emit(OpCodes.Isinst, dstType); + + //push new value + il.Emit(OpCodes.Ldarg_1); + FieldInfo fiNewValue = typeof(ValueChangeEventArgs).GetField("NewValue"); + il.Emit(OpCodes.Ldfld, fiNewValue); + + PropertyInfo piTarget = dstType.GetProperty(binding.MemberName); + MethodInfo miToStr = typeof(object).GetMethod("ToString",Type.EmptyTypes); + + if (!srcValueType.IsValueType) + il.Emit(OpCodes.Castclass, srcValueType); + il.Emit(OpCodes.Callvirt, miToStr); + il.Emit(OpCodes.Callvirt, piTarget.GetSetMethod()); + } + il.MarkLabel(labFailed); + il.Emit(OpCodes.Ret); + + #endregion + + Delegate del = dm.CreateDelegate(ei.EventHandlerType); + MethodInfo addHandler = ei.GetAddMethod (); + //Delegate del = dm.CreateDelegate(typeof(System.EventHandler)); + addHandler.Invoke(_source, new object[] {del}); + } + + public static FieldInfo getEventHandlerField(Type type, string eventName) { FieldInfo fi; diff --git a/src/EventSource.cs b/src/DynAttribute.cs index d8065cd1..db2be2b0 100755 --- a/src/EventSource.cs +++ b/src/DynAttribute.cs @@ -5,10 +5,10 @@ using System.Text; namespace go
{
- public class EventSource
+ public class DynAttribute
{
public GraphicObject Source;
- public string EventName;
- public String Handler;
+ public string MemberName;
+ public String Value;
}
}
diff --git a/src/GraphicObjects/Checkbox.cs b/src/GraphicObjects/Checkbox.cs index 3c25c741..586855d9 100644 --- a/src/GraphicObjects/Checkbox.cs +++ b/src/GraphicObjects/Checkbox.cs @@ -242,11 +242,11 @@ namespace go public override void ReadXml(System.Xml.XmlReader reader)
{
string handler = reader.GetAttribute("OnClick");
- Interface.EventsToResolve.Add(new EventSource
+ Interface.EventsToResolve.Add(new DynAttribute
{
Source = this,
- Handler = handler,
- EventName = "OnClick"
+ Value = handler,
+ MemberName = "OnClick"
});
//Container c = this as Container;
diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs index a7b9e93e..683e88f3 100644 --- a/src/GraphicObjects/GraphicObject.cs +++ b/src/GraphicObjects/GraphicObject.cs @@ -108,6 +108,7 @@ namespace go public event EventHandler<KeyboardKeyEventArgs> KeyUp;
public event EventHandler Focused;
public event EventHandler Unfocused;
+
#endregion
#region public properties
@@ -641,11 +642,11 @@ namespace go if (string.IsNullOrEmpty (handler))
continue;
- Interface.EventsToResolve.Add(new EventSource
+ Interface.EventsToResolve.Add(new DynAttribute
{
Source = this,
- Handler = handler,
- EventName = ei.Name
+ Value = handler,
+ MemberName = ei.Name
});
}
foreach (PropertyInfo pi in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) {
@@ -713,6 +714,19 @@ namespace go else
pi.SetValue (this, defaultValue, null);
} else {
+ if (v.StartsWith("{")) {
+ //binding
+ if (!v.EndsWith("}"))
+ throw new Exception (string.Format("GOML:Malformed binding: {0}", v));
+
+ string strBinding = v.Substring (1, v.Length - 2);
+ Interface.Bindings.Add (new DynAttribute () {
+ Source = this,
+ MemberName = name,
+ Value = strBinding
+ });
+ }
+
if (pi.PropertyType == typeof(string)) {
pi.SetValue (this, v, null);
continue;
diff --git a/src/GraphicObjects/Group.cs b/src/GraphicObjects/Group.cs index 7b63156f..a2a04e0b 100644 --- a/src/GraphicObjects/Group.cs +++ b/src/GraphicObjects/Group.cs @@ -120,7 +120,10 @@ namespace go return tmp;
}
-
+ public override void RegisterForLayouting (int layoutType)
+ {
+ base.RegisterForLayouting (layoutType);
+ }
public override Rectangle ContextCoordinates(Rectangle r){
return r + ClientRectangle.Position;
diff --git a/src/GraphicObjects/IValueChange.cs b/src/GraphicObjects/IValueChange.cs new file mode 100644 index 00000000..4dc886b0 --- /dev/null +++ b/src/GraphicObjects/IValueChange.cs @@ -0,0 +1,30 @@ +// +// IValueChange.cs +// +// Author: +// Jean-Philippe Bruyère <jp.bruyere@hotmail.com> +// +// Copyright (c) 2015 jp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +using System; + +namespace go +{ + public interface IValueChange + { + event EventHandler<ValueChangeEventArgs> ValueChanged; + } +} + diff --git a/src/GraphicObjects/Image.cs b/src/GraphicObjects/Image.cs index aa3ea56d..3858aebc 100755 --- a/src/GraphicObjects/Image.cs +++ b/src/GraphicObjects/Image.cs @@ -71,7 +71,6 @@ namespace go hSVG = new Rsvg.Handle (ms.ToArray ());
imgSize = new Size (hSVG.Dimensions.Width, hSVG.Dimensions.Height);
_imgPath = resId;
- //loadImage (@"Images/Icons/question_mark.svg");
}
}
//load image via System.Drawing.Bitmap, cairo load png only
diff --git a/src/GraphicObjects/NumericControl.cs b/src/GraphicObjects/NumericControl.cs index 93aadc84..2eb54bca 100644 --- a/src/GraphicObjects/NumericControl.cs +++ b/src/GraphicObjects/NumericControl.cs @@ -13,10 +13,10 @@ namespace go public NumericControl(double minimum, double maximum, double step) : base() { - _minValue = minimum; - _maxValue = maximum; - _smallStep = step; - _bigStep = step * 5; + minValue = minimum; + maxValue = maximum; + smallStep = step; + bigStep = step * 5; } #endregion @@ -30,54 +30,54 @@ namespace go #endregion #region private fields - double _actualValue, _minValue, _maxValue, _smallStep, _bigStep; + double _actualValue, minValue, maxValue, smallStep, bigStep; #endregion #region public properties [XmlAttributeAttribute()][DefaultValue(0)] public virtual double Minimum { - get { return _minValue; } + get { return minValue; } set { - if (_minValue == value) + if (minValue == value) return; - _minValue = value; + minValue = value; } } [XmlAttributeAttribute()][DefaultValue(10.0)] public virtual double Maximum { - get { return _maxValue; } + get { return maxValue; } set { - if (_maxValue == value) + if (maxValue == value) return; - _maxValue = value; + maxValue = value; } } [XmlAttributeAttribute()][DefaultValue(0.5)] public virtual double SmallIncrement { - get { return _smallStep; } + get { return smallStep; } set { - if (_smallStep == value) + if (smallStep == value) return; - _smallStep = value; + smallStep = value; } } [XmlAttributeAttribute()][DefaultValue(2.0)] public virtual double LargeIncrement { - get { return _bigStep; } + get { return bigStep; } set { - if (_bigStep == value) + if (bigStep == value) return; - _bigStep = value; + bigStep = value; } } @@ -90,16 +90,16 @@ namespace go if (value == _actualValue) return; - Decimal oldV = (Decimal)_actualValue; + int oldV = Convert.ToInt32(_actualValue); - if (value < _minValue) - _actualValue = _minValue; - else if (value > _maxValue) - _actualValue = _maxValue; + if (value < minValue) + _actualValue = minValue; + else if (value > maxValue) + _actualValue = maxValue; else _actualValue = value; - onValueChanged(this,new ValueChangeEventArgs(oldV,(Decimal)_actualValue)); + onValueChanged(this,new ValueChangeEventArgs("Value", oldV, Convert.ToInt32( _actualValue))); registerForGraphicUpdate(); } } diff --git a/src/GraphicObjects/Spinner.cs b/src/GraphicObjects/Spinner.cs new file mode 100644 index 00000000..dcf0d3d4 --- /dev/null +++ b/src/GraphicObjects/Spinner.cs @@ -0,0 +1,43 @@ +// +// Spinner.cs +// +// Author: +// Jean-Philippe Bruyère <jp.bruyere@hotmail.com> +// +// Copyright (c) 2015 jp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +using System; + +namespace go +{ + public class Spinner : NumericControl + { + public Spinner (double minimum, double maximum, double step) : + base (minimum, maximum, step) + { + butUp = new Button (); + butUp.setChild (new Image ("go.Image.Icons.updown.svg")); + } + public Spinner () : base() + { + } + + Button butUp; + Button butDown; + Label labCpt; + + } +} + diff --git a/src/GraphicObjects/TextBox.cs b/src/GraphicObjects/TextBox.cs index 20403789..28e7c74c 100644 --- a/src/GraphicObjects/TextBox.cs +++ b/src/GraphicObjects/TextBox.cs @@ -15,7 +15,7 @@ namespace go public class TextBoxWidget : Label
{
#region CTOR
- public TextBoxWidget(string _initialValue, GOEvent _onTextChanged = null)
+ public TextBoxWidget(string _initialValue)
: base(_initialValue)
{
@@ -25,19 +25,6 @@ namespace go { }
#endregion
- static bool _capitalOn = false; //????????????????
- [XmlIgnore]public static bool capitalOn
- {
- get
- {
- return _capitalOn;
- //Keyboard[Key.ShiftLeft] || Keyboard[Key.ShiftRight] ?
- //!_capitalOn : _capitalOn;
- }
- set { _capitalOn = value; }
- }
-
-
#region GraphicObject overrides
[XmlIgnore]public override bool HasFocus //trigger update when lost focus to errase text beam
{
@@ -71,23 +58,7 @@ namespace go protected override void onDraw (Context gr)
{
base.onDraw (gr);
- // gr.FontOptions.Antialias = Antialias.Subpixel;
- // gr.FontOptions.HintMetrics = HintMetrics.On;
-// gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
-// gr.SetFontSize (Font.Size);
-
FontExtents fe = gr.FontExtents;
-
-
-
-// gr.MoveTo(rText.X, rText.Y + fe.Ascent);
-// #if _WIN32 || _WIN64
-// gr.ShowText(txt);
-// #elif __linux__
-// gr.ShowText(Text);
-// #endif
-// gr.Fill();
-
}
#endregion
diff --git a/src/Interface.cs b/src/Interface.cs index 8684d851..776dd9a6 100644 --- a/src/Interface.cs +++ b/src/Interface.cs @@ -25,6 +25,7 @@ using System.Reflection; using System.Diagnostics; using System.Collections.Generic; using System.Xml; +using System.Linq; namespace go { @@ -35,11 +36,17 @@ namespace go public static bool ReplaceTabsWithSpace = false; public static bool DesignerMode = false; + /// <summary> + /// Graphic objects References use in dynamic delegates for binding + /// </summary> + public static List<object> References = new List<object>(); + public static LayoutingQueue LayoutingQueue = new LayoutingQueue(); #region Load/Save - internal static List<EventSource> EventsToResolve; + internal static List<DynAttribute> EventsToResolve; + internal static List<DynAttribute> Bindings; public static void Save<T>(string file, T graphicObject) { @@ -68,12 +75,13 @@ namespace go } } Type t = Type.GetType("go." + root); - var go = Activator.CreateInstance(t); + //var go = Activator.CreateInstance(t); return Load(path, t); } public static void Load<T>(string file, out T result, object ClassContainingHandlers = null) { - EventsToResolve = new List<EventSource>(); + EventsToResolve = new List<DynAttribute>(); + Bindings = new List<DynAttribute> (); XmlSerializerNamespaces xn = new XmlSerializerNamespaces(); xn.Add("", ""); @@ -87,32 +95,42 @@ namespace go if (ClassContainingHandlers == null) return; - foreach (EventSource es in EventsToResolve) + foreach (DynAttribute es in EventsToResolve) { - if (string.IsNullOrEmpty(es.Handler)) + if (string.IsNullOrEmpty(es.Value)) continue; - if (es.Handler.StartsWith ("{")) { + if (es.Value.StartsWith ("{")) { CompilerServices.CompileEventSource (es); } else { - MethodInfo mi = ClassContainingHandlers.GetType ().GetMethod (es.Handler, BindingFlags.NonPublic | BindingFlags.Public + MethodInfo mi = ClassContainingHandlers.GetType ().GetMethod (es.Value, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); if (mi == null) { - Debug.WriteLine ("Handler Method not found: " + es.Handler); + Debug.WriteLine ("Handler Method not found: " + es.Value); continue; } - FieldInfo fi = CompilerServices.getEventHandlerField (es.Source.GetType (), es.EventName); + FieldInfo fi = CompilerServices.getEventHandlerField (es.Source.GetType (), es.MemberName); Delegate del = Delegate.CreateDelegate(fi.FieldType, ClassContainingHandlers, mi); fi.SetValue(es.Source, del); } } + + foreach (DynAttribute binding in Bindings) { +// Type tSource = binding.Source.GetType (); +// if (!tSource.GetInterfaces ().Any (i => i.Name == "IValueChange")){ +// Debug.WriteLine ("Binding source does not implement IValueChange."); +// continue; +// } + //MemberInfo mi = binding.Source.GetType ().GetMember (binding.MemberName); + CompilerServices.CreateBinding (binding, ClassContainingHandlers); + } } public static GraphicObject Load(string file, Type type, object ClassContainingHandlers = null) { GraphicObject result; - EventsToResolve = new List<EventSource>(); + EventsToResolve = new List<DynAttribute>(); XmlSerializerNamespaces xn = new XmlSerializerNamespaces(); xn.Add("", ""); @@ -126,23 +144,23 @@ namespace go if (ClassContainingHandlers == null) return result; - foreach (EventSource es in EventsToResolve) + foreach (DynAttribute es in EventsToResolve) { - if (string.IsNullOrEmpty(es.Handler)) + if (string.IsNullOrEmpty(es.Value)) continue; - if (es.Handler.StartsWith ("{")) { + if (es.Value.StartsWith ("{")) { CompilerServices.CompileEventSource (es); } else { - MethodInfo mi = ClassContainingHandlers.GetType ().GetMethod (es.Handler, BindingFlags.NonPublic | BindingFlags.Public + MethodInfo mi = ClassContainingHandlers.GetType ().GetMethod (es.Value, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); if (mi == null) { - Debug.WriteLine ("Handler Method not found: " + es.Handler); + Debug.WriteLine ("Handler Method not found: " + es.Value); continue; } - FieldInfo fi = CompilerServices.getEventHandlerField (es.Source.GetType (), es.EventName); + FieldInfo fi = CompilerServices.getEventHandlerField (es.Source.GetType (), es.MemberName); Delegate del = Delegate.CreateDelegate(fi.FieldType, ClassContainingHandlers, mi); fi.SetValue(es.Source, del); } diff --git a/src/TextChangeEventArgs.cs b/src/TextChangeEventArgs.cs index b826fe4a..726c9ae9 100644 --- a/src/TextChangeEventArgs.cs +++ b/src/TextChangeEventArgs.cs @@ -4,11 +4,14 @@ namespace go { public class ValueChangeEventArgs: EventArgs { - public Decimal OldValue; - public Decimal NewValue; + public string MemberName; + public object OldValue; + public object NewValue; - public ValueChangeEventArgs (Decimal _oldValue, Decimal _newValue) : base() + + public ValueChangeEventArgs (string _memberName, object _oldValue, object _newValue) : base() { + MemberName = _memberName; OldValue = _oldValue; NewValue = _newValue; } |