aboutsummaryrefslogtreecommitdiffstatsci
path: root/src
diff options
context:
space:
mode:
authorjpbruyere <jp.bruyere@hotmail.com>2015-05-18 18:13:48 +0200
committerjpbruyere <jp.bruyere@hotmail.com>2015-05-18 18:13:48 +0200
commitfd19c1fd6960faf9b7131a4dfade4bba95abcf81 (patch)
tree59653a3db212e877aa125884e85e11333bc474cd /src
parent2a48f25993b48535eb84f0e83e4dd7c064ed6e49 (diff)
Simple bindings
demonstration in testFps
Diffstat (limited to 'src')
-rw-r--r--src/CompilerServices/CompilerServices.cs112
-rwxr-xr-xsrc/DynAttribute.cs (renamed from src/EventSource.cs)6
-rw-r--r--src/GraphicObjects/Checkbox.cs6
-rw-r--r--src/GraphicObjects/GraphicObject.cs20
-rw-r--r--src/GraphicObjects/Group.cs5
-rw-r--r--src/GraphicObjects/IValueChange.cs30
-rwxr-xr-xsrc/GraphicObjects/Image.cs1
-rw-r--r--src/GraphicObjects/NumericControl.cs46
-rw-r--r--src/GraphicObjects/Spinner.cs43
-rw-r--r--src/GraphicObjects/TextBox.cs31
-rw-r--r--src/Interface.cs50
-rw-r--r--src/TextChangeEventArgs.cs9
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;
}