= Porting wxWidgets (wx.NET) C# source file to cobra = The .NET wrapper library ([http://wxnet.sourceforge.net wx.NET]) for [http://www.wxwidgets.org wxWidgets] is an interesting case for cobra since it is one of the few .NET libraries that uses a lowercase namespace.[[br]] Consequently there are some complications with persuading cobra to work with it conveniently. see [wiki:C#Diffs Cobra differences from C#] Heres a process for C# generally with some notes re wx.NET generated from converting wx.NET sample file !ListView.cs.[[br]] (See !ListView.cs and converted !ListView.cobra attachment files at end of this page.) 1 Take .cs file, rename to .cobra file. 2. Change multi-line comments from multiple // or /* */ bounded to be /# #/ bounded.[[br]] Change single line comments to use leading '#' Remove extraneous separator line comments between method calls {{{ // ------------------------------ }}} 3. Remove trailing ';' from each line they occur on 4. Fixup blocking and indentation. Remove all '{' and '}' indicating start and end blocks from source.[[br]] Ensure remaining blocks are all correctly (equally) indented and that indentation uses either all spaces or all Tabs and that the indents are in multiples of either 4 spaces or 1 tab. 5. Fix 'using' statements ''''using'''' -> ''''use''''' Remove any lines for {{{ using System using System.Collections.Generic using System.IO using System.Text }}} as cobra includes these automagically Change any other lines from ''''using xxxx;'''' to ''''use xxxx'''' You also need to specify to use the C# wrapper library/namespace for wxWidgets (''''wx''''). Before ''''use System.Drawing'''' add a ''''use .. from line'''' for wx.NET {{{ use wx from "wx.NET" use System.Drawing }}} or add an explicit compiler directive ref line and a 'use wx' line {{{ @ref "wx.NET" ... use wx use System.Drawing }}} 6. Namespace decl Namespaces in cobra need to start with an upcased letter. Remove any ''''wx.'''' prefix from namespace line ; ''''namespace wx.Something'''' to ''''namespace Something'''' 7. Correct any Enum definitions. [[br]] After applying the above its basically removing trailing ',' and ensuring indentation of enum items is the same e.g. {{{ enum Cmd { About, Quit, Dialog } }}} -> {{{ enum Cmd About Quit Dialog enum ID_CONTROLS { ID_RADIO_ORIENT = 5999, ID_CHK_SHOWIMAGES, ID_BTN_NEXT_PAGE, ID_NOTEBOOK } }}} -> {{{ enum ID_CONTROLS ID_RADIO_ORIENT = 5999 ID_CHK_SHOWIMAGES ID_BTN_NEXT_PAGE ID_NOTEBOOK }}} 8. Fix class declaration syntax Change lines like ''''class X : Y'''' to ''''class X inherits Y'''' 9. Change any class instance attributes/fields to be prefixed with ''''var'''' change type and accessmodifier to cobra forms {{{ name = ; --> var name as = }}} 10. Fixup class constructor definitions For initializer/constructor change lines like {{{ public ClassName(params,...) : base(baseParams,...) }}} to {{{ cue init(params, ...) is public base.init(baseParams,...) }}} Within the params list correct type declaration syntax from C# to cobra {{{ [ ...] name, -> name as [is , ...], }}} public is default accessModifier so can leave that off e.g. {{{ public ListViewFrame (string title, Point pos, Size size) : base(title, pos, size) -> cue init(title as String, pos as Point, size as Size ) is public base.init (title, pos, size) }}} 11. Remove any uses of ''''new'''' to construct a class instance, instead just make a call to the class type passing any initializer args, i.e just remove 'new'[[br]] e.g. {{{ menuFile = new Menu() -> menuFile = Menu() new Point(10, 100) -> Point(10, 100) new Size(650,340) -> Size(650, 340) }}} For classes that construct delegates (take method names) prefix the methodname with '''ref''', methodNames must start with a lowercase letter and are prefixed by ''''this.'''' or just ''''.'''' so change the methodName accordingly e.g. {{{new EventListener( OnAbout ) -> EventListener( ref .onAbout ) }}} 12. Methods: Prefix methods with '''def'''.[[br]] Change methodnames to start with a lowercase letter, [[br]] Change param definitions to cobra form.[[br]] {{{[ ...] name,}}} -> {{{name as [is , ...],}}} Cobra methods by default return void and are public so if the C# code specifies '''public void''' you can just delete those words. Also, if a method has no parameters then the empty trailing () can be left off. Note builtin types: C# string -> String[[br]] C# object -> Object [[br]] Theres a twist though; wx.NET also defines an Object (wx.Object) so that if you just declare something of Type Object theres a resolution ambiguity message is 'Ambiguous reference "Object" found in namespaces "System" and "wx"' so you have to either rely on the dynamic typing or resolve the ambiguity by specifying the namespace to use e.g. {{{ public void OnAbout( object sender, Event e ) -> def onAbout(sender as System.Object, e as Event) # OR def onAbout(sender, e as Event) # untyped arg defaults to dynamic # no param method public override bool OnInit() -> def onInit as bool is override # or def onInit as bool is public, override # explicit }}} 13. Calls to methods, properties and attributes/fields. Instance method names, properties and fields are called with a prefix of ''''this.'''' or just ''''.'''' [[br]] and they all must be named starting with a lowercase letter so these calls and settings[[br]] must be modified accordingly. e.g. {{{ menuFile.AppendWL(... -> menuFile.appendWL( ... CreateStatusBar() -> .createStatusBar # or this.createStatusBar }}} Similarly with properties and fields {{{ TextCtrl = new TextCtrl(this, ... -> .textCtrl = TextCtrl(this, ... MenuBar = menuBar -> .menuBar = menuBar Log.SetActiveTarget( textCtrl ) -> Log.setActiveTarget(.textCtrl) # static class }}} If a method takes no args then any empty trailing () on a method call can/should be left off. 14. Property definition. Depending on the property use, prefix properties with :[[br]] * get - readable property only * set - settable property only * pro - gettable and settable Change property names to start with a lowercase letter 15. Local variables declared and assigned on first use can usually be changed to remove the type definition (type inferred from the assignment) or can continue to be explicitly typed (if that compiles). {{{ ListItem info = new ListItem() -> info = ListItem() # or info as ListItem = ListItem() }}} Heres a composite example {{{ // C# ListItem itemCol = new ListItem(); itemCol.Text = "Second Column"; itemCol.Align = ListCtrl.wxLIST_FORMAT_CENTER; itemCol.Width = 300; InsertColumn( 1, itemCol ); --> # Cobra itemCol = ListItem() itemCol.text = "Second Column" itemCol.align = ListCtrl.wxLIST_FORMAT_CENTER itemCol.width = 300 .insertColumn(1, itemCol) }}} 16. Fixup 'For' loops {{{ for ( name = start ; name < stop; ++name ) -> for name as Type in start : stop : 1 # explicit or equally use shortcuts: for name in start : stop : 1 for name in start : stop # if step is one (1) for name in stop # if start is zero (0) and step is one (1) # same as for name in 0 : stop : 1 }}} e.g {{{ for ( int i = 0; i < 200; ++i ) -> for i in 0 : 200 }}} 17. Casting Casts of form '(Type)name' become 'name to Type' e.g. {{{ mf.AppendWL( (int)Cmd.About,... -> mf.appendWL(Cmd.About to int,... }}} Casts of form 'a as Type' can also become 'name to Type' or 'name to? Type' e.g {{{ ListEvent le = e as ListEvent; -> le = e to ListEvent }}} 18. String catenated with an expression (converted to string) Put the expression (cobra converted) in the string inside [] e.g. {{{ "Value 1st field of selected item: " + le.Text -> "Value 1st field of selected item: [le.text]" }}} 19. Adding eventHandlers Cobra uses the '''listen''' statement to register event handlers where C# uses an override on the += operator. !WxWidgets wraps method calls in an !EventHandler delegate class instance.[[br]] Otherwise normal cobra mapping for method names and reference to methods (vs method calls)apply;[[br]] Methodnames in Cobra must start with a lower case letter and calls to this instance names are prefixed with ''''this.'''' or (easier) ''''.'''' When translating from a 'use'd library namespace, calls to[[br]] Capcased methodnames are referenced in cobra with the first '''char''' lowercased,[[br]] Upcased methodnames are referenced with the first '''word''' lowercased so {{{ EVENT += new EventListener( MethodName ) in C# becomes listen .EVENT, EventListener( ref .methodName ) EVENT += new EventListener( EH_METHOD_NAME ) in C# becomes listen .EVENT, EventListener( ref .eh_METHOD_NAME ) }}} e.g. {{{ ColumnClick += new EventListener( OnColumnClick ) ItemSelect += new EventListener( OnItemSelect ) ColumnRightClick += new EventListener( OnColumnRightClick ) -> listen .columnClick, EventListener(ref .onColumnClick) listen .itemSelect, EventListener(ref .onItemSelect ) listen .columnRightClick, EventListener(ref .onColumnRightClick) }}} !WxWidgets menu action handlers can be done in C# using call to EVT_MENU. {{{EVT_MENU((int)MENU_ENUM_VALUE, new EventListener(MethodName)); }}} the equivalent in cobra becomes {{{.evt_MENU(MENU_ENUM_VALUE to int, EventListener(ref .methodName))}}} e.g. {{{ EVT_MENU((int)Cmd.Quit, new EventListener(OnQuit)); EVT_MENU((int)Cmd.Dialog, new EventListener(OnDialog)); EVT_MENU((int)Cmd.About, new EventListener(OnAbout)); }}} -> {{{ .evt_MENU(Cmd.Quit to int, EventListener(ref .onQuit)) .evt_MENU(Cmd.Dialog to int, EventListener(ref .onDialog)) .evt_MENU(Cmd.About to int, EventListener(ref .onAbout)) }}} 20. Main method 'public void' is default, static is an accessmodifier which becomes ''''shared'''' in cobra, C# attributes (!MetaInformation) are denoted with ''''has'''' e.g. {{{ [STAThread] static public void main() }}} to {{{ def main is shared has STAThread }}} 21. Lowercased namespace names (as in wx.NET) used to disambiguate or otherwise explicitly [[br]] specify the namespace on types (inherits ..., as ....) as opposed to methods or constants [[br]] can (may/will) generate compile errors of the form: [[br]] '''error: Cannot find type for "wx.TYPE".'''[[br]] e.g. error: Cannot find type for "wx.Frame".[[br]] If such occurs the only recourse is to remove the explicit typing and rely on default handling. [[br]] e.g. {{{ use wx from "wx.NET" namespace SampleMinimal class MyFrame inherits wx.Frame # file.cobra(3): error: Cannot find type for "wx.Frame". }}} change to {{{ use wx from "wx.NET" namespace SampleMinimal class MyFrame inherits Frame }}} {{{ def onAbout(sender as System.Object, e as wx.Event ) }}} [[br]] change to [[br]] {{{ def onAbout(sender as System.Object, e as Event ) }}} [[br]] {{{fileMenu as wx.Menu = wx.Menu() }}} [[br]] change to [[br]] {{{fileMenu = Menu() }}} [[br]] Eventually it would be preferable if cobra became a little more flexible in these cases.. ----- Other weirdnesses: As of this doc date (Oct 2009) the wx.NET version and cobra seem to not be able to find some properties, specifically[[br]] Frame.Icon, .icon property -> no workaround. [[br]] Frame.!StatusBar, .statusBar text property -> use method .setStatusBar(text) instead.[[br]] These and much of the above issues with recognising lowercased namespace references should be corrected (or at least improved) with the fix to ticket:184.