[Ironruby-core] Form Designer adding delegates

Dermot Hogan lists at ruby-forum.com
Thu Oct 25 12:48:44 EDT 2007


Wayne Kelly wrote:
>> >     @button1.set_Location(System::Drawing::Point.new(47, 54))
>>
>> Is there a reason why you're calling the property setter
>> method explicitly rather than using the property name? Or is
>> this not supported in the Ruby.Net method binder?
> 
> Our compiler would be happy with it as a property assignment, but we did 
> it that way inside InitializeComponent in order to ensure round 
> tripping. When parsing InitializeComponent and generating the codeDOM 
> representation we need to distinguish between a field, a property and a 
> method call. Statically typed languages are expected to use type 
> information to distinguish. As we have no type information we use 
> syntactic conventions to distinguish between them. Note - these 
> syntactic conventions only apply within the InitializeComponent method 
> which is typically auto-generated. Ruby programmers are free to use the 
> more Rubyish syntax elsewhere in their code.
> 

You don't need to do this, I think. You can work out from the context 
what is a field, a property and a call. I did have some initial trouble 
distinguishing between a Property (System.Windows.Form.BackColor.Red) 
and an enum (System.Windows.Form.BorderStyle.Sizable) - but it worked 
out ok.

> Another issue is statically distinguishing between variables such as Foo 
> and type references such as System::Drawing::Point - we use 
> wrapper/helper methods to distinguish type references (except when 
> invoking a new method where we implicitly assume that the constant is a 
> type reference). Again, this is only necessary inside 
> IntializeComponent.
> 
I didn't have that problem. But what I did have a problem with was 
something like this (from a TreeNode control):

treeNode3 = System::Windows::Forms::TreeNode.new('Node0', [treeNode1, 
treeNode2])

Here, the FormDesigner needs to know the type of the array - which Ruby 
of course doesn't give you. That took a bit of time to get right.

> 
> And now a question for your VS integration experts: when adding a new 
> event handler - how do you arrange for the cursor to be automatically 
> placed inside the body of the new method?
> 

I'm sure there are several ways to do this, but this is what I did:

1) I have two files - the form code file and the designer file (as in 
C#). In the CodeDomProvider, I override the Parse method and *before* I 
parse the designer file to generate the CodeDom, I scan the form file 
looking for event handlers. I use regexps to do this - I don't bother 
Ruby parsing the form file at all. I then build a list containing the 
names and positions of any event handlers.

2) I then Ruby parse (using Antlr) the designer file and generate the 
CodeDom from that. When a delegate is required I do something like this:

CodeMemberMethod cmm = new CodeMemberMethod();
cmm.Parameters.Add(new 
CodeParameterDeclarationExpression(typeof(object), "sender"));
cmm.Parameters.Add(new 
CodeParameterDeclarationExpression(typeof(System.EventArgs), "e"));
cmm.Name = eventHandlerName;

// let the provider process adding the event handler
int line = _provider.AddEventHandler(eventHandlerName);
cmm.UserData.Add(typeof(Point), new Point(0, line + 1));

The AddEventHandler method does the business of finding any event 
handler in the form code, generating it if required (again in the form 
code - not the designer code) and returning its position. The last bit 
is the code that lets the FormDesigner know where the event handler is 
when you double click on the control in the form.

Something similar happems when you drop a new control on the form.

Splitting the form code from the designer makes life a whole lot simpler 
and the coding is then clear and unambiguous. And most importantly from 
my point of view, it's easily maintainable.


Dermot

-- 
Posted via http://www.ruby-forum.com/.


More information about the Ironruby-core mailing list