diff --git a/src/bindings/mono/eina_mono/eina_value.cs b/src/bindings/mono/eina_mono/eina_value.cs index 627c7cb343..99cf09757d 100644 --- a/src/bindings/mono/eina_mono/eina_value.cs +++ b/src/bindings/mono/eina_mono/eina_value.cs @@ -182,6 +182,10 @@ static internal class UnsafeNativeMethods [return: MarshalAsAttribute(UnmanagedType.U1)] internal static extern bool eina_value_container_append_wrapper_string(IntPtr handle, string data); + [DllImport(efl.Libs.CustomExports)] + [return: MarshalAsAttribute(UnmanagedType.U1)] + internal static extern bool eina_value_container_append_wrapper_ptr(IntPtr handle, IntPtr data); + [DllImport(efl.Libs.CustomExports)] [return: MarshalAsAttribute(UnmanagedType.U1)] internal static extern bool eina_value_container_append_wrapper_char(IntPtr handle, sbyte data); @@ -278,6 +282,10 @@ static internal class UnsafeNativeMethods [return: MarshalAsAttribute(UnmanagedType.U1)] internal static extern bool eina_value_container_set_wrapper_string(IntPtr handle, int index, string value); + [DllImport(efl.Libs.CustomExports)] + [return: MarshalAsAttribute(UnmanagedType.U1)] + internal static extern bool eina_value_container_set_wrapper_ptr(IntPtr handle, int index, IntPtr value); + [DllImport(efl.Libs.CustomExports)] [return: MarshalAsAttribute(UnmanagedType.U1)] internal static extern bool eina_value_container_set_wrapper_uchar(IntPtr handle, int index, byte value); @@ -378,6 +386,10 @@ static internal class UnsafeNativeMethods [return: MarshalAsAttribute(UnmanagedType.U1)] internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, ref string value); + [DllImport(efl.Libs.Eina)] + [return: MarshalAsAttribute(UnmanagedType.U1)] + internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, ref IntPtr value); + [DllImport(efl.Libs.Eina)] [return: MarshalAsAttribute(UnmanagedType.U1)] internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, IntPtr value); @@ -507,6 +519,10 @@ static internal class UnsafeNativeMethods // Error [DllImport(efl.Libs.CustomExports)] internal static extern IntPtr type_error(); + + // Error + [DllImport(efl.Libs.CustomExports)] + internal static extern IntPtr type_object(); } } @@ -613,6 +629,7 @@ public enum ValueType Optional, /// Error values. Error, + Object, /// Empty values. Empty, } @@ -675,6 +692,11 @@ static class ValueTypeMethods return val == ValueType.Error; } + public static bool IsObject(this ValueType val) + { + return val == ValueType.Object; + } + /// Returns the Marshal.SizeOf for the given ValueType native structure. public static int MarshalSizeOf(this ValueType val) { @@ -771,6 +793,9 @@ static class ValueTypeBridge ManagedToNative.Add(ValueType.Error, type_error()); NativeToManaged.Add(type_error(), ValueType.Error); + ManagedToNative.Add(ValueType.Object, type_object()); + NativeToManaged.Add(type_object(), ValueType.Object); + ManagedToNative.Add(ValueType.Empty, IntPtr.Zero); NativeToManaged.Add(IntPtr.Zero, ValueType.Empty); @@ -1354,6 +1379,32 @@ public class Value : IDisposable, IComparable, IEquatable return b; } + // Efl.Object conversions are made explicit to avoid ambiguity between + // Set(Efl.Object) and Set(Value) when dealing with classes derived from + // Efl.Object. + /// Explicit conversion from EFL objects. + public static explicit operator Value(Efl.Object obj) + { + var v = new Eina.Value(ValueType.Object); + if (!v.Set(obj)) + { + throw new InvalidOperationException("Couldn't set value."); + } + return v; + } + + /// Explicit conversion from Value to Efl.Objects. + public static explicit operator Efl.Object(Value v) + { + Efl.Object obj; + if (!v.Get(out obj)) + { + throw new InvalidOperationException("Couldn't get value."); + } + + return obj; + } + /// Creates an Value instance from a given array description. private static Value FromArrayDesc(Eina.EinaNative.Value_Array arrayDesc) { @@ -1789,6 +1840,22 @@ public class Value : IDisposable, IComparable, IEquatable return eina_value_set_wrapper_int(this.Handle, error_code); } + /// Stores the given object. + public bool Set(Efl.Object value) + { + // FIXME Implement me + SanityChecks(); + + if (this.Optional) + { + IntPtr ptr = value.NativeHandle; + return eina_value_optional_pset(this.Handle, + ValueTypeBridge.GetNative(ValueType.Object), + ref ptr); + } + return eina_value_set_wrapper_ptr(this.Handle, value.NativeHandle); + } + /// Stores the given value into this value. The target value must be an optional. public bool Set(Value value) { @@ -2017,6 +2084,36 @@ public class Value : IDisposable, IComparable, IEquatable return ret; } + /// Gets the currently stored value as an . + public bool Get(out Efl.Object obj) + { + // FIXME Implement me + SanityChecks(); + IntPtr ptr; + bool ret; + + if (this.Optional) + { + ret = eina_value_optional_pget(this.Handle, out ptr); + } + else + { + ret = eina_value_get_wrapper(this.Handle, out ptr); + } + + if (ret) + { + obj = (Efl.Object) Efl.Eo.Globals.CreateWrapperFor(ptr); + } + else + { + obj = null; + } + + return ret; + } + + /// Gets the currently stored value as an complex (e.g. container) Eina.Value. public bool Get(out Value value) { @@ -2281,6 +2378,11 @@ public class Value : IDisposable, IComparable, IEquatable string x = Convert.ToString(o); return eina_value_container_append_wrapper_string(this.Handle, x); } + case ValueType.Object: + { + var x = (Efl.Object) o; + return eina_value_container_append_wrapper_ptr(this.Handle, x.NativeHandle); + } } return false; @@ -2374,6 +2476,12 @@ public class Value : IDisposable, IComparable, IEquatable eina_value_container_get_wrapper(this.Handle, i, out ptr); return Eina.StringConversion.NativeUtf8ToManagedString(ptr); } + case ValueType.Object: + { + IntPtr ptr = IntPtr.Zero; + eina_value_container_get_wrapper(this.Handle, i, out ptr); + return Efl.Eo.Globals.CreateWrapperFor(ptr); + } default: throw new InvalidOperationException("Subtype not supported."); @@ -2463,6 +2571,12 @@ public class Value : IDisposable, IComparable, IEquatable eina_value_container_set_wrapper_string(this.Handle, i, x); break; } + case ValueType.Object: + { + Efl.Object x = (Efl.Object)value; + eina_value_container_set_wrapper_ptr(this.Handle, i, x.NativeHandle); + break; + } } } } diff --git a/src/lib/efl_mono/efl_custom_exports_mono.c b/src/lib/efl_mono/efl_custom_exports_mono.c index 55f0054da0..ad74babe52 100644 --- a/src/lib/efl_mono/efl_custom_exports_mono.c +++ b/src/lib/efl_mono/efl_custom_exports_mono.c @@ -403,6 +403,9 @@ EAPI const Eina_Value_Type *type_list() { EAPI const Eina_Value_Type *type_error() { return EINA_VALUE_TYPE_ERROR; } +EAPI const Eina_Value_Type *type_object() { + return EINA_VALUE_TYPE_OBJECT; +} EAPI const Eina_Value_Type *type_optional() { return EINA_VALUE_TYPE_OPTIONAL; diff --git a/src/tests/efl_mono/Value.cs b/src/tests/efl_mono/Value.cs index 2c5e3115f0..75b8e96ca1 100644 --- a/src/tests/efl_mono/Value.cs +++ b/src/tests/efl_mono/Value.cs @@ -146,6 +146,31 @@ public static class TestEinaValue { } } + public static void TestObjectSimple() + { + using (Eina.Value v = new Eina.Value(Eina.ValueType.Object)) + { + var obj = new Dummy.TestObject(); + Test.Assert(v.Set(obj)); + Efl.Object target; + Test.Assert(v.Get(out target)); + Test.AssertEquals(target, obj); + } + } + + // Efl.Object conversions are made explicit to avoid ambiguity between + // Set(Efl.Object) and Set(Value) when dealing with classes derived from + // Efl.Object. + public static void TestObjectImplicit() + { + var obj = new Dummy.TestObject(); + var v = (Eina.Value)obj; + Test.AssertEquals(v.GetValueType(), Eina.ValueType.Object); + Efl.Object target = (Efl.Object)v; + + Test.AssertEquals(target, obj); + } + public static void TestSetWrongType() { using (Eina.Value v = new Eina.Value(Eina.ValueType.String)) { @@ -259,6 +284,37 @@ public static class TestEinaValue { Test.AssertEquals(expected, actual); } } + + public static void TestValueOptionalObject() + { + using (Eina.Value a = new Eina.Value(Eina.ValueType.Object)) { + Test.Assert(!a.Optional); + BoolRet dummy = () => a.OptionalEmpty; + Test.AssertRaises(() => dummy()); + } + + using (Eina.Value a = new Eina.Value(Eina.ValueType.Optional)) { + Test.Assert(a.Optional); + Test.Assert(a.OptionalEmpty); // By default, optional values are empty + + // Sets expectation + Efl.Object expected = new Dummy.TestObject(); + Test.Assert(a.Set(expected)); + Test.Assert(a.Optional); + Test.Assert(!a.OptionalEmpty); + + Test.Assert(a.Reset()); + Test.Assert(a.OptionalEmpty); + + Test.Assert(a.Set(expected)); + Test.Assert(!a.OptionalEmpty); + + Efl.Object received = null; + Test.Assert(a.Get(out received)); + Test.AssertEquals(expected, received); + } + } + public static void TestValueOptionalArrays() { using (Eina.Value a = new Eina.Value(Eina.ValueType.Optional)) @@ -763,6 +819,30 @@ public static class TestEinaValue { } } + public static void TestValueArrayOfObjects() + { + + using(Eina.Value array = new Eina.Value(Eina.ValueType.Array, Eina.ValueType.Object)) { + + var a = new Dummy.TestObject(); + var b = new Dummy.TestObject(); + + Test.Assert(array.Append(a)); + Test.Assert(array.Append(b)); + + Test.AssertEquals((Efl.Object)array[0], a); + Test.AssertEquals((Efl.Object)array[1], b); + + var c = new Dummy.TestObject(); + array[0] = c; + array[1] = b; + + Test.AssertEquals((Efl.Object)array[0], c); + Test.AssertEquals((Efl.Object)array[1], b); + } + } + + public static void TestArrayOutOfBounds() { using(Eina.Value array = new Eina.Value(Eina.ValueType.Array, Eina.ValueType.Int32)) { object placeholder = null;