summaryrefslogtreecommitdiff
path: root/src/bin/eolian_mono/eolian/mono/klass.hh
diff options
context:
space:
mode:
authorLauro Moura <lauromoura@expertisesolutions.com.br>2018-11-29 21:04:37 -0200
committerVitor Sousa <vitorsousa@expertisesolutions.com.br>2018-11-29 21:29:48 -0200
commit3623753c1d6b893955a1c31e8559a2312f674192 (patch)
treee862682ff92d34ce4ebf44c95efa24ba3a57fe7a /src/bin/eolian_mono/eolian/mono/klass.hh
parenteec7bc458eee333fd7237a3bd43e8c2c884f21ca (diff)
csharp: Change to new class API.
Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
Diffstat (limited to 'src/bin/eolian_mono/eolian/mono/klass.hh')
-rw-r--r--src/bin/eolian_mono/eolian/mono/klass.hh534
1 files changed, 356 insertions, 178 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh
index 7a40511..077a0fa 100644
--- a/src/bin/eolian_mono/eolian/mono/klass.hh
+++ b/src/bin/eolian_mono/eolian/mono/klass.hh
@@ -4,6 +4,7 @@
4#include "grammar/integral.hpp" 4#include "grammar/integral.hpp"
5#include "grammar/generator.hpp" 5#include "grammar/generator.hpp"
6#include "grammar/klass_def.hpp" 6#include "grammar/klass_def.hpp"
7#include "grammar/attribute_conditional.hpp"
7#include "blacklist.hh" 8#include "blacklist.hh"
8 9
9#include "grammar/indentation.hpp" 10#include "grammar/indentation.hpp"
@@ -35,11 +36,11 @@ static bool generate_static_cast_method(OutputIterator sink, grammar::attributes
35{ 36{
36 return as_generator( 37 return as_generator(
37 scope_tab << "///<summary>Casts obj into an instance of this type.</summary>\n" 38 scope_tab << "///<summary>Casts obj into an instance of this type.</summary>\n"
38 << scope_tab << "public static " << name_helpers::klass_interface_name(cls) << " static_cast(efl.IObject obj)\n" 39 << scope_tab << "public " << (helpers::has_regular_ancestor(cls) ? "new " : "") <<"static " << name_helpers::klass_concrete_name(cls) << " static_cast(Efl.Object obj)\n"
39 << scope_tab << "{\n" 40 << scope_tab << "{\n"
40 << scope_tab << scope_tab << "if (obj == null)\n" 41 << scope_tab << scope_tab << "if (obj == null)\n"
41 << scope_tab << scope_tab << scope_tab << "throw new System.ArgumentNullException(\"obj\");\n" 42 << scope_tab << scope_tab << scope_tab << "throw new System.ArgumentNullException(\"obj\");\n"
42 << scope_tab << scope_tab << "return new " << name_helpers::klass_concrete_name(cls) << "(obj.raw_handle);\n" 43 << scope_tab << scope_tab << "return new " << name_helpers::klass_concrete_name(cls) << "(obj.NativeHandle);\n"
43 << scope_tab << "}\n" 44 << scope_tab << "}\n"
44 ).generate(sink, nullptr, context); 45 ).generate(sink, nullptr, context);
45} 46}
@@ -51,29 +52,29 @@ static bool generate_equals_method(OutputIterator sink, Context const &context)
51 scope_tab << "///<summary>Verifies if the given object is equal to this one.</summary>\n" 52 scope_tab << "///<summary>Verifies if the given object is equal to this one.</summary>\n"
52 << scope_tab << "public override bool Equals(object obj)\n" 53 << scope_tab << "public override bool Equals(object obj)\n"
53 << scope_tab << "{\n" 54 << scope_tab << "{\n"
54 << scope_tab << scope_tab << "var other = obj as efl.IObject;\n" 55 << scope_tab << scope_tab << "var other = obj as Efl.Object;\n"
55 << scope_tab << scope_tab << "if (other == null)\n" 56 << scope_tab << scope_tab << "if (other == null)\n"
56 << scope_tab << scope_tab << scope_tab << "return false;\n" 57 << scope_tab << scope_tab << scope_tab << "return false;\n"
57 << scope_tab << scope_tab << "return this.raw_handle == other.raw_handle;\n" 58 << scope_tab << scope_tab << "return this.NativeHandle == other.NativeHandle;\n"
58 << scope_tab << "}\n" 59 << scope_tab << "}\n"
59 << scope_tab << "///<summary>Gets the hash code for this object based on the native pointer it points to.</summary>\n" 60 << scope_tab << "///<summary>Gets the hash code for this object based on the native pointer it points to.</summary>\n"
60 << scope_tab << "public override int GetHashCode()\n" 61 << scope_tab << "public override int GetHashCode()\n"
61 << scope_tab << "{\n" 62 << scope_tab << "{\n"
62 << scope_tab << scope_tab << "return this.raw_handle.ToInt32();\n" 63 << scope_tab << scope_tab << "return this.NativeHandle.ToInt32();\n"
63 << scope_tab << "}\n" 64 << scope_tab << "}\n"
64 << scope_tab << "///<summary>Turns the native pointer into a string representation.</summary>\n" 65 << scope_tab << "///<summary>Turns the native pointer into a string representation.</summary>\n"
65 << scope_tab << "public override String ToString()\n" 66 << scope_tab << "public override String ToString()\n"
66 << scope_tab << "{\n" 67 << scope_tab << "{\n"
67 << scope_tab << scope_tab << "return $\"{this.GetType().Name}@[{this.raw_handle.ToInt32():x}]\";\n" 68 << scope_tab << scope_tab << "return $\"{this.GetType().Name}@[{this.NativeHandle.ToInt32():x}]\";\n"
68 << scope_tab << "}\n" 69 << scope_tab << "}\n"
69 ).generate(sink, nullptr, context); 70 ).generate(sink, nullptr, context);
70} 71}
71 72
72/* Get the actual number of functions of a class, checking for blacklisted ones */ 73/* Get the actual number of functions of a class, checking for blacklisted ones */
73static std::size_t 74static std::size_t
74get_inheritable_function_count(grammar::attributes::klass_def const& cls) 75get_implementable_function_count(grammar::attributes::klass_def const& cls)
75{ 76{
76 auto methods = cls.get_all_methods(); 77 auto methods = helpers::get_all_implementable_methods(cls);
77 return std::count_if(methods.cbegin(), methods.cend(), [](grammar::attributes::function_def const& func) 78 return std::count_if(methods.cbegin(), methods.cend(), [](grammar::attributes::function_def const& func)
78 { 79 {
79 return !blacklist::is_function_blacklisted(func.c_name) && !func.is_static; 80 return !blacklist::is_function_blacklisted(func.c_name) && !func.is_static;
@@ -97,6 +98,9 @@ struct klass
97 switch(cls.type) 98 switch(cls.type)
98 { 99 {
99 case attributes::class_type::regular: 100 case attributes::class_type::regular:
101 class_type = "class";
102 suffix = "CLASS";
103 break;
100 case attributes::class_type::abstract_: 104 case attributes::class_type::abstract_:
101 class_type = "class"; 105 class_type = "class";
102 suffix = "CLASS"; 106 suffix = "CLASS";
@@ -117,6 +121,7 @@ struct klass
117 auto methods = cls.get_all_methods(); 121 auto methods = cls.get_all_methods();
118 122
119 // Interface class 123 // Interface class
124 if(class_type == "interface")
120 { 125 {
121 auto iface_cxt = context_add_tag(class_context{class_context::interface}, context); 126 auto iface_cxt = context_add_tag(class_context{class_context::interface}, context);
122 127
@@ -132,11 +137,12 @@ struct klass
132 for(auto first = std::begin(cls.immediate_inherits) 137 for(auto first = std::begin(cls.immediate_inherits)
133 , last = std::end(cls.immediate_inherits); first != last; ++first) 138 , last = std::end(cls.immediate_inherits); first != last; ++first)
134 { 139 {
135 if(!as_generator("\n" << scope_tab << string << " ,").generate(sink, name_helpers::klass_full_interface_name(*first), iface_cxt)) 140 if(first->type != attributes::class_type::regular && first->type != attributes::class_type::abstract_)
136 return false; 141 if(!as_generator("\n" << scope_tab << string << " ,").generate(sink, name_helpers::klass_full_interface_name(*first), iface_cxt))
142 return false;
137 } 143 }
138 144
139 if(!as_generator("\n" << scope_tab << "efl.eo.IWrapper, IDisposable").generate(sink, attributes::unused, iface_cxt)) 145 if(!as_generator("\n" << scope_tab << "Efl.Eo.IWrapper, IDisposable").generate(sink, attributes::unused, iface_cxt))
140 return false; 146 return false;
141 147
142 if(!as_generator("\n{\n").generate(sink, attributes::unused, iface_cxt)) 148 if(!as_generator("\n{\n").generate(sink, attributes::unused, iface_cxt))
@@ -154,85 +160,74 @@ struct klass
154 for (auto &&p : cls.parts) 160 for (auto &&p : cls.parts)
155 if (!as_generator( 161 if (!as_generator(
156 documentation(1) 162 documentation(1)
157 << name_helpers::klass_full_interface_name(p.klass) << " " << utils::capitalize(p.name) << "{ get;}\n" 163 << name_helpers::klass_full_concrete_or_interface_name(p.klass) << " " << utils::capitalize(p.name) << "{ get;}\n"
158 ).generate(sink, p, iface_cxt)) 164 ).generate(sink, p, iface_cxt))
159 return false; 165 return false;
160 166
161 // End of interface declaration 167 // End of interface declaration
162 if(!as_generator("}\n").generate(sink, attributes::unused, iface_cxt)) return false; 168 if(!as_generator("}\n").generate(sink, attributes::unused, iface_cxt)) return false;
169
163 } 170 }
164 171
165 // Concrete class 172 // Events arguments go in the top namespace to avoid the Concrete suffix clutter in interface events.
166 // if(class_type == "class") 173 // Regular/abstract class events go here too for consistency.
174 if(!as_generator(*(event_argument_wrapper)).generate(sink, cls.events, context))
175 return false;
176
177 bool root = !helpers::has_regular_ancestor(cls);
178 std::set<attributes::klass_name, attributes::compare_klass_name_by_name> inherit_interfaces = helpers::non_implemented_interfaces(cls);
179 std::vector<attributes::klass_name> inherit_classes;
180 std::copy_if(cls.immediate_inherits.begin(), cls.immediate_inherits.end()
181 , std::back_inserter(inherit_classes)
182 , [] (attributes::klass_name const& klass)
183 {
184 switch (klass.type)
185 {
186 case attributes::class_type::regular:
187 case attributes::class_type::abstract_:
188 return true;
189 default:
190 return false;
191 };
192 });
193
194 // Concrete class for interfaces, mixins, etc.
195 if(class_type != "class")
167 { 196 {
168 auto concrete_cxt = context_add_tag(class_context{class_context::concrete}, context); 197 auto concrete_cxt = context_add_tag(class_context{class_context::concrete}, context);
169 auto concrete_name = name_helpers::klass_concrete_name(cls); 198 auto concrete_name = name_helpers::klass_concrete_name(cls);
170 auto interface_name = name_helpers::klass_interface_name(cls); 199 auto interface_name = name_helpers::klass_interface_name(cls);
200
171 if(!as_generator 201 if(!as_generator
172 ( 202 (
173 documentation 203 documentation
174 << "sealed public class " << concrete_name << " : " << interface_name << "\n{\n" 204 << "sealed public class " << concrete_name << " : " << "\n"
175 << scope_tab << "System.IntPtr handle;\n" 205 << (klass_full_concrete_or_interface_name % ",") << "\n"
176 << scope_tab << "///<summary>Pointer to the native instance.</summary>\n" 206 << (inherit_classes.size() > 0 ? ", " : "" ) << interface_name << "\n"
177 << scope_tab << "public System.IntPtr raw_handle {\n" 207 << scope_tab << *(", " << name_helpers::klass_full_concrete_or_interface_name) << "\n"
178 << scope_tab << scope_tab << "get { return handle; }\n" 208 << "{\n"
179 << scope_tab << "}\n" 209 ).generate(sink, std::make_tuple(cls, inherit_classes, inherit_interfaces), concrete_cxt))
180 << scope_tab << "///<summary>Pointer to the native class description.</summary>\n" 210 return false;
181 << scope_tab << "public System.IntPtr raw_klass {\n" 211
182 << scope_tab << scope_tab << "get { return efl.eo.Globals.efl_class_get(handle); }\n" 212 if (!generate_fields(sink, cls, concrete_cxt))
183 << scope_tab << "}\n" 213 return false;
184 << scope_tab << "///<summary>Delegate for function to be called from inside the native constructor.</summary>\n" 214
185 << scope_tab << "public delegate void ConstructingMethod(" << interface_name << " obj);\n" 215 if (!as_generator
186 << scope_tab << "///<summary>Returns the pointer the underlying Eo class object. Used internally on class methods.</summary>\n" 216 (
187 << scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(concrete_cxt).actual_library_name(cls.filename) 217 scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(concrete_cxt).actual_library_name(cls.filename)
188 << ")] public static extern System.IntPtr\n" 218 << ")] internal static extern System.IntPtr\n"
189 << scope_tab << scope_tab << name_helpers::klass_get_name(cls) << "();\n" 219 << scope_tab << scope_tab << name_helpers::klass_get_name(cls) << "();\n"
190 << (class_type == "class" ? "" : "/*")
191 << scope_tab << "///<summary>Creates a new instance.</summary>\n"
192 << scope_tab << "///<param>Parent instance.</param>\n"
193 << scope_tab << "///<param>Delegate to call constructing methods that should be run inside the constructor.</param>\n"
194 << scope_tab << "public " << concrete_name << "(efl.IObject parent = null, ConstructingMethod init_cb=null)\n"
195 << scope_tab << "{\n"
196 << scope_tab << scope_tab << "System.IntPtr klass = " << name_helpers::klass_get_name(cls) << "();\n"
197 << scope_tab << scope_tab << "System.IntPtr parent_ptr = System.IntPtr.Zero;\n"
198 << scope_tab << scope_tab << "if(parent != null)\n"
199 << scope_tab << scope_tab << scope_tab << "parent_ptr = parent.raw_handle;\n"
200 << scope_tab << scope_tab << "handle = efl.eo.Globals._efl_add_internal_start(\"file\", 0, klass, parent_ptr, 1, 0);\n"
201 << scope_tab << scope_tab << "register_event_proxies();\n"
202 << scope_tab << scope_tab << "if (init_cb != null) {\n"
203 << scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
204 << scope_tab << scope_tab << "}\n"
205 << scope_tab << scope_tab << "handle = efl.eo.Globals._efl_add_end(handle, 1, 0);\n" // replace handle with the actual final handle
206 << scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n"
207 << scope_tab << "}\n"
208 << (class_type == "class" ? "" : "*/")
209 << scope_tab << "///<summary>Constructs an instance from a native pointer.</summary>\n" 220 << scope_tab << "///<summary>Constructs an instance from a native pointer.</summary>\n"
210 << scope_tab << "public " << concrete_name << "(System.IntPtr raw)\n" 221 << scope_tab << "public " << concrete_name << "(System.IntPtr raw)\n"
211 << scope_tab << "{\n" 222 << scope_tab << "{\n"
212 << scope_tab << scope_tab << "handle = raw;\n" 223 << scope_tab << scope_tab << "handle = raw;\n"
213 << scope_tab << scope_tab << "register_event_proxies();\n" 224 << scope_tab << scope_tab << "register_event_proxies();\n"
214 << scope_tab << "}\n" 225 << scope_tab << "}\n"
215 << scope_tab << "///<summary>Destructor.</summary>\n"
216 << scope_tab << "~" << concrete_name << "()\n"
217 << scope_tab << "{\n"
218 << scope_tab << scope_tab << "Dispose(false);\n"
219 << scope_tab << "}\n"
220 << scope_tab << "///<summary>Releases the underlying native instance.</summary>\n"
221 << scope_tab << "internal void Dispose(bool disposing)\n"
222 << scope_tab << "{\n"
223 << scope_tab << scope_tab << "if (handle != System.IntPtr.Zero) {\n"
224 << scope_tab << scope_tab << scope_tab << "efl.eo.Globals.efl_unref(handle);\n"
225 << scope_tab << scope_tab << scope_tab << "handle = System.IntPtr.Zero;\n"
226 << scope_tab << scope_tab << "}\n"
227 << scope_tab << "}\n"
228 << scope_tab << "///<summary>Releases the underlying native instance.</summary>\n"
229 << scope_tab << "public void Dispose()\n"
230 << scope_tab << "{\n"
231 << scope_tab << scope_tab << "Dispose(true);\n"
232 << scope_tab << scope_tab << "GC.SuppressFinalize(this);\n"
233 << scope_tab << "}\n"
234 ) 226 )
235 .generate(sink, cls, concrete_cxt)) 227 .generate(sink, attributes::unused, concrete_cxt))
228 return false;
229
230 if (!generate_dispose_methods(sink, cls, concrete_cxt))
236 return false; 231 return false;
237 232
238 if (!generate_static_cast_method(sink, cls, concrete_cxt)) 233 if (!generate_static_cast_method(sink, cls, concrete_cxt))
@@ -249,100 +244,53 @@ struct klass
249 244
250 // Parts 245 // Parts
251 if(!as_generator(*(part_definition)) 246 if(!as_generator(*(part_definition))
252 .generate(sink, cls.get_all_parts(), concrete_cxt)) return false; 247 .generate(sink, cls.parts, concrete_cxt)) return false;
253 248
254 // Concrete function definitions 249 // Concrete function definitions
250 auto implemented_methods = helpers::get_all_implementable_methods(cls);
255 if(!as_generator(*(function_definition)) 251 if(!as_generator(*(function_definition))
256 .generate(sink, methods, concrete_cxt)) return false; 252 .generate(sink, implemented_methods, concrete_cxt)) return false;
257 253
258 // Async wrappers 254 // Async wrappers
259 if(!as_generator(*(async_function_definition)).generate(sink, methods, concrete_cxt)) 255 if(!as_generator(*(async_function_definition)).generate(sink, implemented_methods, concrete_cxt))
260 return false;
261
262 if(!as_generator(*(event_argument_wrapper)).generate(sink, cls.events, context))
263 return false; 256 return false;
264 257
265 if(!as_generator("}\n").generate(sink, attributes::unused, concrete_cxt)) return false; 258 if(!as_generator("}\n").generate(sink, attributes::unused, concrete_cxt)) return false;
259
266 } 260 }
267 261
268 // Inherit class 262 // Inheritable class
269 if(class_type == "class") 263 if(class_type == "class")
270 { 264 {
271 auto inherit_cxt = context_add_tag(class_context{class_context::inherit}, context); 265 auto inherit_cxt = context_add_tag(class_context{class_context::inherit}, context);
272 bool cls_has_string_return = has_string_return(cls);
273 bool cls_has_stringshare_return = has_stringshare_return(cls);
274
275 auto interface_name = name_helpers::klass_interface_name(cls);
276 auto inherit_name = name_helpers::klass_inherit_name(cls);
277 auto native_inherit_name = name_helpers::klass_native_inherit_name(cls);
278
279 266
280 if(!as_generator 267 // Class header
268 if(!as_generator
281 ( 269 (
282 documentation 270 documentation
283 << "public " << class_type << " " << inherit_name << " : " << interface_name << "\n{\n" 271 << "public " << class_type << " " << name_helpers::klass_concrete_name(cls) << " : "
284 << scope_tab << "System.IntPtr handle;\n" 272 << (klass_full_concrete_or_interface_name % ",") // classes
285 << scope_tab << "internal static System.IntPtr klass = System.IntPtr.Zero;\n" 273 << (inherit_classes.empty() ? "" : ",")
286 << scope_tab << "private static readonly object klassAllocLock = new object();\n" 274 << " Efl.Eo.IWrapper" << (root ? ", IDisposable" : "")
287 << scope_tab << (cls_has_string_return ? ("internal Dictionary<String, IntPtr> cached_strings = new Dictionary<String, IntPtr>();") : "") << "\n" 275 << (inherit_interfaces.empty() ? "" : ",")
288 << scope_tab << (cls_has_stringshare_return ? ("internal Dictionary<String, IntPtr> cached_stringshares = new Dictionary<String, IntPtr>();") : "") << "\n" 276 << (klass_full_concrete_or_interface_name % ",") // interfaces
289 << scope_tab << "///<summary>Pointer to the native instance.</summary>\n" 277 << "\n{\n"
290 << scope_tab << "public System.IntPtr raw_handle {\n" 278 )
291 << scope_tab << scope_tab << "get { return handle; }\n" 279 .generate(sink, std::make_tuple(cls, inherit_classes, inherit_interfaces), inherit_cxt))
292 << scope_tab << "}\n" 280 return false;
293 << scope_tab << "///<summary>Pointer to the native class description.</summary>\n" 281
294 << scope_tab << "public System.IntPtr raw_klass {\n" 282
295 << scope_tab << scope_tab << "get { return klass; }\n" 283 // Class body
296 << scope_tab << "}\n" 284 if(!generate_fields(sink, cls, inherit_cxt))
297 << scope_tab << "///<summary>Delegate for function to be called from inside the native constructor.</summary>\n" 285 return false;
298 << scope_tab << "public delegate void ConstructingMethod(" << interface_name << " obj);\n" 286
299 << scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(inherit_cxt).actual_library_name(cls.filename) 287 if (!generate_constructors(sink, cls, inherit_cxt))
300 << ")] private static extern System.IntPtr\n" 288 return false;
301 << scope_tab << scope_tab << name_helpers::klass_get_name(cls) << "();\n" 289
302 << scope_tab << "///<summary>Creates a new instance.</summary>\n" 290 if (!generate_dispose_methods(sink, cls, inherit_cxt))
303 << scope_tab << "///<param>Parent instance.</param>\n" 291 return false;
304 << scope_tab << "///<param>Delegate to call constructing methods that should be run inside the constructor.</param>\n" 292
305 << scope_tab << "public " << inherit_name << "(efl.IObject parent = null, ConstructingMethod init_cb=null)\n" 293 if (!generate_static_cast_method(sink, cls, inherit_cxt))
306 << scope_tab << "{\n"
307 << scope_tab << scope_tab << "if (klass == System.IntPtr.Zero) {\n"
308 << scope_tab << scope_tab << scope_tab << "lock (klassAllocLock) {\n"
309 << scope_tab << scope_tab << scope_tab << scope_tab << "if (klass == System.IntPtr.Zero) {\n"
310 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "klass = efl.eo.Globals.register_class(new efl.eo.Globals.class_initializer(" << native_inherit_name << ".class_initializer), \"" << cls.eolian_name << "\", " << name_helpers::klass_get_name(cls) << "());\n"
311 << scope_tab << scope_tab << scope_tab << scope_tab << "}\n"
312 << scope_tab << scope_tab << scope_tab << "}\n"
313 << scope_tab << scope_tab << "}\n"
314 << scope_tab << scope_tab << "handle = efl.eo.Globals.instantiate_start(klass, parent);\n"
315 << scope_tab << scope_tab << "register_event_proxies();\n"
316 << scope_tab << scope_tab << "if (init_cb != null) {\n"
317 << scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
318 << scope_tab << scope_tab << "}\n"
319 << scope_tab << scope_tab << "efl.eo.Globals.data_set(this);\n"
320 << scope_tab << scope_tab << "handle = efl.eo.Globals.instantiate_end(handle);\n"
321 << scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n"
322 << scope_tab << "}\n"
323 << scope_tab << "///<summary>Destructor.</summary>\n"
324 << scope_tab << "~" << inherit_name << "()\n"
325 << scope_tab << "{\n"
326 << scope_tab << scope_tab << "Dispose(false);\n"
327 << scope_tab << "}\n"
328 << scope_tab << "///<summary>Releases the underlying native instance.</summary>\n"
329 << scope_tab << "protected virtual void Dispose(bool disposing)\n"
330 << scope_tab << "{\n"
331 << scope_tab << scope_tab << "if (handle != System.IntPtr.Zero) {\n"
332 << scope_tab << scope_tab << scope_tab << "efl.eo.Globals.efl_unref(handle);\n"
333 << scope_tab << scope_tab << scope_tab << "handle = System.IntPtr.Zero;\n"
334 << scope_tab << scope_tab << "}\n"
335 << scope_tab << "}\n"
336 << scope_tab << "///<summary>Releases the underlying native instance.</summary>\n"
337 << scope_tab << "public void Dispose()\n"
338 << scope_tab << "{\n"
339 << scope_tab << (cls_has_string_return ? "efl.eo.Globals.free_dict_values(cached_strings);" : "") << "\n"
340 << scope_tab << (cls_has_stringshare_return ? "efl.eo.Globals.free_stringshare_values(cached_stringshares);" : "") << "\n"
341 << scope_tab << scope_tab << "Dispose(true);\n"
342 << scope_tab << scope_tab << "GC.SuppressFinalize(this);\n"
343 << scope_tab << "}\n"
344 )
345 .generate(sink, cls, inherit_cxt))
346 return false; 294 return false;
347 295
348 if (!generate_equals_method(sink, inherit_cxt)) 296 if (!generate_equals_method(sink, inherit_cxt))
@@ -356,20 +304,21 @@ struct klass
356 304
357 // Parts 305 // Parts
358 if(!as_generator(*(part_definition)) 306 if(!as_generator(*(part_definition))
359 .generate(sink, cls.get_all_parts(), inherit_cxt)) return false; 307 .generate(sink, cls.parts, inherit_cxt)) return false;
360 308
361 // Inherit function definitions 309 // Inherit function definitions
310 auto implemented_methods = helpers::get_all_implementable_methods(cls);
362 if(!as_generator(*(function_definition(true))) 311 if(!as_generator(*(function_definition(true)))
363 .generate(sink, methods, inherit_cxt)) return false; 312 .generate(sink, implemented_methods, inherit_cxt)) return false;
364 313
365 // Async wrappers 314 // Async wrappers
366 if(!as_generator(*(async_function_definition(true))).generate(sink, methods, inherit_cxt)) 315 if(!as_generator(*(async_function_definition(true))).generate(sink, implemented_methods, inherit_cxt))
367 return false; 316 return false;
368 317
369 if(!as_generator("}\n").generate(sink, attributes::unused, inherit_cxt)) return false; 318 if(!as_generator("}\n").generate(sink, attributes::unused, inherit_cxt)) return false;
370 } 319 }
371 320
372 std::size_t function_count = get_inheritable_function_count(cls); 321 std::size_t function_count = get_implementable_function_count(cls);
373 322
374 int function_registration_index = 0; 323 int function_registration_index = 0;
375 auto index_generator = [&function_registration_index] 324 auto index_generator = [&function_registration_index]
@@ -394,7 +343,7 @@ struct klass
394 343
395 // Native wrapper registration 344 // Native wrapper registration
396 if(!as_generator(*(function_registration(index_generator, cls))) 345 if(!as_generator(*(function_registration(index_generator, cls)))
397 .generate(sink, methods, inative_cxt)) return false; 346 .generate(sink, helpers::get_all_implementable_methods(cls), inative_cxt)) return false;
398 347
399 if(!as_generator 348 if(!as_generator
400 ( scope_tab << scope_tab << "IntPtr descs_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(descs[0])*" << function_count << ");\n" 349 ( scope_tab << scope_tab << "IntPtr descs_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(descs[0])*" << function_count << ");\n"
@@ -409,7 +358,7 @@ struct klass
409 << scope_tab << scope_tab << "ops.count = (UIntPtr)" << function_count << ";\n" 358 << scope_tab << scope_tab << "ops.count = (UIntPtr)" << function_count << ";\n"
410 << scope_tab << scope_tab << "IntPtr ops_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ops));\n" 359 << scope_tab << scope_tab << "IntPtr ops_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ops));\n"
411 << scope_tab << scope_tab << "Marshal.StructureToPtr(ops, ops_ptr, false);\n" 360 << scope_tab << scope_tab << "Marshal.StructureToPtr(ops, ops_ptr, false);\n"
412 << scope_tab << scope_tab << "efl.eo.Globals.efl_class_functions_set(klass, ops_ptr, IntPtr.Zero);\n" 361 << scope_tab << scope_tab << "Efl.Eo.Globals.efl_class_functions_set(klass, ops_ptr, IntPtr.Zero);\n"
413 ).generate(sink, attributes::unused, inative_cxt)) return false; 362 ).generate(sink, attributes::unused, inative_cxt)) return false;
414 363
415 364
@@ -419,7 +368,7 @@ struct klass
419 // 368 //
420 // Native method definitions 369 // Native method definitions
421 if(!as_generator(*(native_function_definition(cls))) 370 if(!as_generator(*(native_function_definition(cls)))
422 .generate(sink, methods, inative_cxt)) return false; 371 .generate(sink, helpers::get_all_implementable_methods(cls), inative_cxt)) return false;
423 372
424 if(!as_generator("}\n").generate(sink, attributes::unused, inative_cxt)) return false; 373 if(!as_generator("}\n").generate(sink, attributes::unused, inative_cxt)) return false;
425 } 374 }
@@ -431,11 +380,222 @@ struct klass
431 } 380 }
432 381
433 template <typename OutputIterator, typename Context> 382 template <typename OutputIterator, typename Context>
383 bool generate_fields(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
384 {
385 std::string visibility = is_inherit_context(context) ? "protected " : "private ";
386 bool root = !helpers::has_regular_ancestor(cls);
387 bool is_inherit = is_inherit_context(context);
388
389 std::string class_getter = "return Efl.Eo.Globals.efl_class_get(handle);";
390
391 // The klass field is static but there is no problem if multiple C# classes inherit from this generated one
392 // as it is just a simple wrapper, forwarding the Eo calls either to the user API (where C#'s virtual method
393 // resolution kicks in) or to the base implementation (efl_super).
394 if (is_inherit)
395 {
396 if(!as_generator(
397 scope_tab << "public " << (root ? "" : "new ") << "static System.IntPtr klass = System.IntPtr.Zero;\n"
398 ).generate(sink, attributes::unused, context))
399 return false;
400 class_getter = "return klass;";
401 }
402
403 std::string raw_klass_modifier;
404 if (!root)
405 raw_klass_modifier = "override ";
406 else if (is_inherit)
407 raw_klass_modifier = "virtual ";
408
409 if(!as_generator(
410 scope_tab << "///<summary>Pointer to the native class description.</summary>\n"
411 << scope_tab << "public " << raw_klass_modifier << "System.IntPtr NativeClass {\n"
412 << scope_tab << scope_tab << "get {\n"
413 << scope_tab << scope_tab << scope_tab << class_getter << "\n" //return klass; }\n"
414 << scope_tab << scope_tab << "}\n"
415 << scope_tab << "}\n"
416 ).generate(sink, attributes::unused, context))
417 return false;
418
419 // The remaining fields aren't needed in children classes.
420 if (!root)
421 return true;
422
423 if (cls.get_all_events().size() > 0)
424 if (!as_generator(scope_tab << (is_inherit ? "protected " : "private ") << "EventHandlerList eventHandlers = new EventHandlerList();\n").generate(sink, attributes::unused, context))
425 return false;
426
427 if (is_inherit)
428 {
429 if (!as_generator(
430 scope_tab << "private static readonly object klassAllocLock = new object();\n"
431 << scope_tab << "protected bool inherited;\n"
432 ).generate(sink, attributes::unused, context))
433 return false;
434 }
435
436 return as_generator(
437 scope_tab << visibility << " System.IntPtr handle;\n"
438 << scope_tab << "public Dictionary<String, IntPtr> cached_strings = new Dictionary<String, IntPtr>();" << "\n"
439 << scope_tab << "public Dictionary<String, IntPtr> cached_stringshares = new Dictionary<String, IntPtr>();" << "\n"
440 << scope_tab << "///<summary>Pointer to the native instance.</summary>\n"
441 << scope_tab << "public System.IntPtr NativeHandle {\n"
442 << scope_tab << scope_tab << "get { return handle; }\n"
443 << scope_tab << "}\n"
444 ).generate(sink, attributes::unused, context);
445 }
446
447 template <typename OutputIterator, typename Context>
448 bool generate_constructors(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
449 {
450 bool root = !helpers::has_regular_ancestor(cls);
451 auto inherit_name = name_helpers::klass_concrete_name(cls);
452 auto native_inherit_name = name_helpers::klass_native_inherit_name(cls);
453
454 if(!as_generator(
455 scope_tab << "///<summary>Delegate for function to be called from inside the native constructor.</summary>\n"
456 << scope_tab << "public" << (root ? "" : " new") << " delegate void ConstructingMethod(" << inherit_name << " obj);\n"
457 << scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(context).actual_library_name(cls.filename)
458 << ")] internal static extern System.IntPtr\n"
459 << scope_tab << scope_tab << name_helpers::klass_get_name(cls) << "();\n"
460 ).generate(sink, attributes::unused, context))
461 return false;
462
463
464 if (!root)
465 {
466 return as_generator(
467 scope_tab << "///<summary>Creates a new instance.</summary>\n"
468 << scope_tab << "///<param name=\"parent\">Parent instance.</param>\n"
469 << scope_tab << "///<param name=\"init_cb\">Delegate to call constructing methods that should be run inside the constructor.</param>\n"
470 << scope_tab << "public " << inherit_name << "(Efl.Object parent = null, ConstructingMethod init_cb=null) : base(" << native_inherit_name << ".class_initializer, \"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent, ref klass)\n"
471 << scope_tab << "{\n"
472 << scope_tab << scope_tab << "if (init_cb != null) {\n"
473 << scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
474 << scope_tab << scope_tab << "}\n"
475 << scope_tab << scope_tab << "FinishInstantiation();\n"
476 << scope_tab << "}\n"
477
478 << scope_tab << "///<summary>Internal constructor to forward the wrapper initialization to the root class.</summary>\n"
479 << scope_tab << "protected " << inherit_name << "(Efl.Eo.Globals.class_initializer class_initializer, String klass_name, IntPtr base_klass, Type managed_type, Efl.Object parent, ref IntPtr target_klass) : base(class_initializer, klass_name, base_klass, managed_type, parent, ref target_klass) {}\n"
480
481 << scope_tab << "///<summary>Constructs an instance from a native pointer.</summary>\n"
482 << scope_tab << "public " << inherit_name << "(System.IntPtr raw)" << (root ? "" : " : base(raw)") << "\n"
483 << scope_tab << "{\n"
484 << scope_tab << scope_tab << (root ? "handle = raw;\n" : "")
485 << scope_tab << scope_tab << "register_event_proxies();\n"
486 << scope_tab << "}\n"
487 ).generate(sink, attributes::unused, context);
488 }
489
490 // Detailed constructors go only in root classes.
491 return as_generator(
492 scope_tab << "///<summary>Creates a new instance.</summary>\n"
493 << scope_tab << "///<param name=\"parent\">Parent instance.</param>\n"
494 << scope_tab << "///<param name=\"init_cb\">Delegate to call constructing methods that should be run inside the constructor.</param>\n"
495 << scope_tab << "public " << inherit_name << "(Efl.Object parent = null, ConstructingMethod init_cb=null) : this(" << native_inherit_name << ".class_initializer, \"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent, ref klass)\n"
496 << scope_tab << "{\n"
497 << scope_tab << scope_tab << "if (init_cb != null) {\n"
498 << scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
499 << scope_tab << scope_tab << "}\n"
500 << scope_tab << scope_tab << "FinishInstantiation();\n"
501 << scope_tab << "}\n"
502
503 << scope_tab << "protected " << inherit_name << "(Efl.Eo.Globals.class_initializer class_initializer, String klass_name, IntPtr base_klass, Type managed_type, Efl.Object parent, ref IntPtr target_klass)\n"
504 << scope_tab << "{\n"
505 << scope_tab << scope_tab << "inherited = this.GetType() != managed_type;\n"
506 << scope_tab << scope_tab << "IntPtr actual_klass = base_klass;\n"
507 << scope_tab << scope_tab << "if (inherited) {\n"
508 << scope_tab << scope_tab << scope_tab << "if (target_klass == System.IntPtr.Zero) {\n"
509 << scope_tab << scope_tab << scope_tab << scope_tab << "lock (klassAllocLock) {\n"
510 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "if (target_klass == System.IntPtr.Zero) {\n"
511 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "target_klass = Efl.Eo.Globals.register_class(class_initializer, klass_name, base_klass);\n"
512 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "if (target_klass == System.IntPtr.Zero) {\n"
513 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "throw new System.InvalidOperationException(\"Failed to initialize class '" << inherit_name << "'\");\n"
514 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "}\n"
515 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "}\n"
516 << scope_tab << scope_tab << scope_tab << scope_tab << "}\n"
517 << scope_tab << scope_tab << scope_tab << "}\n"
518 << scope_tab << scope_tab << scope_tab << "actual_klass = target_klass;\n"
519 << scope_tab << scope_tab << "}\n"
520 << scope_tab << scope_tab << "handle = Efl.Eo.Globals.instantiate_start(actual_klass, parent);\n"
521 << scope_tab << scope_tab << "register_event_proxies();\n"
522 << scope_tab << "}\n"
523
524 << scope_tab << "protected void FinishInstantiation()\n"
525 << scope_tab << "{\n"
526 << scope_tab << scope_tab << "if (inherited) {\n"
527 << scope_tab << scope_tab << scope_tab << "Efl.Eo.Globals.data_set(this);\n"
528 << scope_tab << scope_tab << "}\n"
529 << scope_tab << scope_tab << "handle = Efl.Eo.Globals.instantiate_end(handle);\n"
530 << scope_tab << scope_tab << "Eina.Error.RaiseIfOccurred();\n"
531 << scope_tab << "}\n"
532
533 << scope_tab << "///<summary>Constructs an instance from a native pointer.</summary>\n"
534 << scope_tab << "public " << inherit_name << "(System.IntPtr raw)\n"
535 << scope_tab << "{\n"
536 << scope_tab << scope_tab << "handle = raw;\n"
537 << scope_tab << scope_tab << "register_event_proxies();\n"
538 << scope_tab << "}\n"
539 ).generate(sink, attributes::unused, context);
540 }
541
542
543 template <typename OutputIterator, typename Context>
544 bool generate_dispose_methods(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
545 {
546 std::string name = join_namespaces(cls.namespaces, '.') + cls.eolian_name;
547 if (helpers::has_regular_ancestor(cls))
548 return true;
549
550 std::string visibility = is_inherit_context(context) ? "protected virtual " : "";
551
552 auto inherit_name = name_helpers::klass_concrete_name(cls);
553
554 return as_generator(
555
556 scope_tab << "///<summary>Destructor.</summary>\n"
557 << scope_tab << "~" << inherit_name << "()\n"
558 << scope_tab << "{\n"
559 << scope_tab << scope_tab << "Dispose(false);\n"
560 << scope_tab << "}\n"
561
562 << scope_tab << "///<summary>Releases the underlying native instance.</summary>\n"
563 << scope_tab << visibility << "void Dispose(bool disposing)\n"
564 << scope_tab << "{\n"
565 << scope_tab << scope_tab << "if (handle != System.IntPtr.Zero) {\n"
566 << scope_tab << scope_tab << scope_tab << "Efl.Eo.Globals.efl_unref(handle);\n"
567 << scope_tab << scope_tab << scope_tab << "handle = System.IntPtr.Zero;\n"
568 << scope_tab << scope_tab << "}\n"
569 << scope_tab << "}\n"
570
571 << scope_tab << "///<summary>Releases the underlying native instance.</summary>\n"
572 << scope_tab << "public void Dispose()\n"
573 << scope_tab << "{\n"
574 << scope_tab << "Efl.Eo.Globals.free_dict_values(cached_strings);" << "\n"
575 << scope_tab << "Efl.Eo.Globals.free_stringshare_values(cached_stringshares);" << "\n"
576 << scope_tab << scope_tab << "Dispose(true);\n"
577 << scope_tab << scope_tab << "GC.SuppressFinalize(this);\n"
578 << scope_tab << "}\n"
579 ).generate(sink, attributes::unused, context);
580 }
581
582 template <typename OutputIterator, typename Context>
434 bool generate_events_registration(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const 583 bool generate_events_registration(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
435 { 584 {
585 bool root = !helpers::has_regular_ancestor(cls);
586 std::string virtual_modifier = " ";
587
588 if (!root)
589 virtual_modifier = "override ";
590 else
591 {
592 if (is_inherit_context(context))
593 virtual_modifier = "virtual ";
594 }
595
436 // Event proxy registration 596 // Event proxy registration
437 if (!as_generator( 597 if (!as_generator(
438 scope_tab << "private void register_event_proxies()\n" 598 scope_tab << (is_inherit_context(context) || !root ? "protected " : "") << virtual_modifier << "void register_event_proxies()\n"
439 << scope_tab << "{\n" 599 << scope_tab << "{\n"
440 ) 600 )
441 .generate(sink, NULL, context)) 601 .generate(sink, NULL, context))
@@ -443,15 +603,23 @@ struct klass
443 603
444 // Generate event registrations here 604 // Generate event registrations here
445 605
606 if (!root)
607 if (!as_generator(scope_tab << scope_tab << "base.register_event_proxies();\n").generate(sink, NULL, context))
608 return false;
609
446 // Assigning the delegates 610 // Assigning the delegates
447 if (!as_generator(*(event_registration())).generate(sink, cls.events, context)) 611 if (!as_generator(*(event_registration(cls, cls))).generate(sink, cls.events, context))
448 return false; 612 return false;
449 613
450 for (auto&& c : cls.inherits) 614 for (auto&& c : helpers::non_implemented_interfaces(cls))
451 { 615 {
616 // Only non-regular types (which declare events through interfaces) need to register them.
617 if (c.type == attributes::class_type::regular)
618 continue;
619
452 attributes::klass_def klass(get_klass(c, cls.unit), cls.unit); 620 attributes::klass_def klass(get_klass(c, cls.unit), cls.unit);
453 621
454 if (!as_generator(*(event_registration(&klass))).generate(sink, klass.events, context)) 622 if (!as_generator(*(event_registration(klass, cls))).generate(sink, klass.events, context))
455 return false; 623 return false;
456 } 624 }
457 625
@@ -470,53 +638,59 @@ struct klass
470 if (!has_events(cls)) 638 if (!has_events(cls))
471 return true; 639 return true;
472 640
473 std::string visibility = is_inherit_context(context) ? "protected" : "private"; 641 std::string visibility = is_inherit_context(context) ? "protected " : "private ";
474 642
475 if (!as_generator(scope_tab << "private readonly object eventLock = new object();\n" 643 if (!helpers::has_regular_ancestor(cls))
476 << scope_tab << "private Dictionary<string, int> event_cb_count = new Dictionary<string, int>();\n") 644 {
477 .generate(sink, NULL, context)) 645 if (!as_generator(scope_tab << visibility << "readonly object eventLock = new object();\n"
478 return false; 646 << scope_tab << visibility << "Dictionary<string, int> event_cb_count = new Dictionary<string, int>();\n")
647 .generate(sink, NULL, context))
648 return false;
479 649
480 // Callback registration functions 650 // Callback registration functions
481 if (!as_generator( 651 if (!as_generator(
482 scope_tab << "private bool add_cpp_event_handler(string key, efl.Event_Cb evt_delegate) {\n" 652 scope_tab << visibility << "bool add_cpp_event_handler(string key, Efl.EventCb evt_delegate) {\n"
483 << scope_tab << scope_tab << "int event_count = 0;\n" 653 << scope_tab << scope_tab << "int event_count = 0;\n"
484 << scope_tab << scope_tab << "if (!event_cb_count.TryGetValue(key, out event_count))\n" 654 << scope_tab << scope_tab << "if (!event_cb_count.TryGetValue(key, out event_count))\n"
485 << scope_tab << scope_tab << scope_tab << "event_cb_count[key] = event_count;\n" 655 << scope_tab << scope_tab << scope_tab << "event_cb_count[key] = event_count;\n"
486 << scope_tab << scope_tab << "if (event_count == 0) {\n" 656 << scope_tab << scope_tab << "if (event_count == 0) {\n"
487 << scope_tab << scope_tab << scope_tab << "IntPtr desc = efl.Event_Description.GetNative(key);\n" 657
658 << scope_tab << scope_tab << scope_tab << "IntPtr desc = Efl.EventDescription.GetNative(key);\n"
488 << scope_tab << scope_tab << scope_tab << "if (desc == IntPtr.Zero) {\n" 659 << scope_tab << scope_tab << scope_tab << "if (desc == IntPtr.Zero) {\n"
489 << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Error($\"Failed to get native event {key}\");\n" 660 << scope_tab << scope_tab << scope_tab << scope_tab << "Eina.Log.Error($\"Failed to get native event {key}\");\n"
490 << scope_tab << scope_tab << scope_tab << scope_tab << "return false;\n" 661 << scope_tab << scope_tab << scope_tab << scope_tab << "return false;\n"
491 << scope_tab << scope_tab << scope_tab << "}\n" 662 << scope_tab << scope_tab << scope_tab << "}\n"
492 << scope_tab << scope_tab << scope_tab << "bool result = efl.eo.Globals.efl_event_callback_priority_add(handle, desc, 0, evt_delegate, System.IntPtr.Zero);\n" 663
664 << scope_tab << scope_tab << scope_tab << " bool result = Efl.Eo.Globals.efl_event_callback_priority_add(handle, desc, 0, evt_delegate, System.IntPtr.Zero);\n"
493 << scope_tab << scope_tab << scope_tab << "if (!result) {\n" 665 << scope_tab << scope_tab << scope_tab << "if (!result) {\n"
494 << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Error($\"Failed to add event proxy for event {key}\");\n" 666 << scope_tab << scope_tab << scope_tab << scope_tab << "Eina.Log.Error($\"Failed to add event proxy for event {key}\");\n"
495 << scope_tab << scope_tab << scope_tab << scope_tab << "return false;\n" 667 << scope_tab << scope_tab << scope_tab << scope_tab << "return false;\n"
496 << scope_tab << scope_tab << scope_tab << "}\n" 668 << scope_tab << scope_tab << scope_tab << "}\n"
497 << scope_tab << scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n" 669 << scope_tab << scope_tab << scope_tab << "Eina.Error.RaiseIfOccurred();\n"
498 << scope_tab << scope_tab << "} \n" 670 << scope_tab << scope_tab << "} \n"
499 << scope_tab << scope_tab << "event_cb_count[key]++;\n" 671 << scope_tab << scope_tab << "event_cb_count[key]++;\n"
500 << scope_tab << scope_tab << "return true;\n" 672 << scope_tab << scope_tab << "return true;\n"
501 << scope_tab << "}\n" 673 << scope_tab << "}\n"
502 << scope_tab << "private bool remove_cpp_event_handler(string key, efl.Event_Cb evt_delegate) {\n" 674 << scope_tab << visibility << "bool remove_cpp_event_handler(string key, Efl.EventCb evt_delegate) {\n"
503 << scope_tab << scope_tab << "int event_count = 0;\n" 675 << scope_tab << scope_tab << "int event_count = 0;\n"
504 << scope_tab << scope_tab << "if (!event_cb_count.TryGetValue(key, out event_count))\n" 676 << scope_tab << scope_tab << "if (!event_cb_count.TryGetValue(key, out event_count))\n"
505 << scope_tab << scope_tab << scope_tab << "event_cb_count[key] = event_count;\n" 677 << scope_tab << scope_tab << scope_tab << "event_cb_count[key] = event_count;\n"
506 << scope_tab << scope_tab << "if (event_count == 1) {\n" 678 << scope_tab << scope_tab << "if (event_count == 1) {\n"
507 << scope_tab << scope_tab << scope_tab << "IntPtr desc = efl.Event_Description.GetNative(key);\n" 679
680 << scope_tab << scope_tab << scope_tab << "IntPtr desc = Efl.EventDescription.GetNative(key);\n"
508 << scope_tab << scope_tab << scope_tab << "if (desc == IntPtr.Zero) {\n" 681 << scope_tab << scope_tab << scope_tab << "if (desc == IntPtr.Zero) {\n"
509 << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Error($\"Failed to get native event {key}\");\n" 682 << scope_tab << scope_tab << scope_tab << scope_tab << "Eina.Log.Error($\"Failed to get native event {key}\");\n"
510 << scope_tab << scope_tab << scope_tab << scope_tab << "return false;\n" 683 << scope_tab << scope_tab << scope_tab << scope_tab << "return false;\n"
511 << scope_tab << scope_tab << scope_tab << "}\n" 684 << scope_tab << scope_tab << scope_tab << "}\n"
512 << scope_tab << scope_tab << scope_tab << "bool result = efl.eo.Globals.efl_event_callback_del(handle, desc, evt_delegate, System.IntPtr.Zero);\n" 685
686 << scope_tab << scope_tab << scope_tab << "bool result = Efl.Eo.Globals.efl_event_callback_del(handle, desc, evt_delegate, System.IntPtr.Zero);\n"
513 << scope_tab << scope_tab << scope_tab << "if (!result) {\n" 687 << scope_tab << scope_tab << scope_tab << "if (!result) {\n"
514 << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Error($\"Failed to remove event proxy for event {key}\");\n" 688 << scope_tab << scope_tab << scope_tab << scope_tab << "Eina.Log.Error($\"Failed to remove event proxy for event {key}\");\n"
515 << scope_tab << scope_tab << scope_tab << scope_tab << "return false;\n" 689 << scope_tab << scope_tab << scope_tab << scope_tab << "return false;\n"
516 << scope_tab << scope_tab << scope_tab << "}\n" 690 << scope_tab << scope_tab << scope_tab << "}\n"
517 << scope_tab << scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n" 691 << scope_tab << scope_tab << scope_tab << "Eina.Error.RaiseIfOccurred();\n"
518 << scope_tab << scope_tab << "} else if (event_count == 0) {\n" 692 << scope_tab << scope_tab << "} else if (event_count == 0) {\n"
519 << scope_tab << scope_tab << scope_tab << "eina.Log.Error($\"Trying to remove proxy for event {key} when there is nothing registered.\");\n" 693 << scope_tab << scope_tab << scope_tab << "Eina.Log.Error($\"Trying to remove proxy for event {key} when there is nothing registered.\");\n"
520 << scope_tab << scope_tab << scope_tab << "return false;\n" 694 << scope_tab << scope_tab << scope_tab << "return false;\n"
521 << scope_tab << scope_tab << "} \n" 695 << scope_tab << scope_tab << "} \n"
522 << scope_tab << scope_tab << "event_cb_count[key]--;\n" 696 << scope_tab << scope_tab << "event_cb_count[key]--;\n"
@@ -525,16 +699,20 @@ struct klass
525 ) 699 )
526 .generate(sink, NULL, context)) 700 .generate(sink, NULL, context))
527 return false; 701 return false;
702 }
528 703
529 // Self events 704 // Self events
530 if (!as_generator(*(event_definition(cls))).generate(sink, cls.events, context)) 705 if (!as_generator(*(event_definition(cls, cls))).generate(sink, cls.events, context))
531 return false; 706 return false;
532 707
533 // Inherited events 708 // Inherited events
534 for (auto&& c : cls.inherits) 709
710 // For now, as mixins can inherit from regular classes, we can't filter out inherited events.
711 auto inherits = helpers::non_implemented_interfaces(cls);
712 for (auto&& c : inherits)
535 { 713 {
536 attributes::klass_def klass(get_klass(c, cls.unit), cls.unit); 714 attributes::klass_def klass(get_klass(c, cls.unit), cls.unit);
537 if (!as_generator(*(event_definition(klass, true))).generate(sink, klass.events, context)) 715 if (!as_generator(*(event_definition(klass, cls))).generate(sink, klass.events, context))
538 return false; 716 return false;
539 } 717 }
540 return true; 718 return true;