Thread overview
Events
Feb 07, 2006
Kyle Furlong
Feb 07, 2006
Kris
Feb 08, 2006
Kyle Furlong
Feb 08, 2006
Shawn Liu
February 07, 2006
Currently, one has to write code like this:

private class MenuArgs
{
	Menu menu;
	Label label;
	this(Menu m, Label l)
	{
		menu = m;
		label = l;
	}
}

MenuArgs args = new MenuArgs(Menu, Label);
					 	
Label.handleMouseDown(args, delegate void(MouseEvent e)
{
	MenuArgs args = cast(MenuArgs)e.cData;
	// Do things with args.
});

But NOT like this:

Label.handleMouseDown(null, delegate void(MouseEvent e)
{
	// Do things with Label and Menu, and any other objects outside this scope.
});

Doing anything with objects outside of the scope of the delegate will cause AccessViolations inside of the DWT eventable.d, unless they are passed as cData.

This seems to be an onerous restriction, and also counterintuitive. Also, all the examples use objects outside the scope of the delegate as well, so that it would seem to be The Right Way, except that it doesnt work.


Is this a bug? Or a feature?
February 07, 2006
"Kyle Furlong" <kylefurlong@gmail.com> wrote ..
[snip]
> Is this a bug? Or a feature?


I suspect what's happening is that your out-of-scope MenuArgs are actually on the stack when you call handleMouseDown(), which is not the case when the delegate is invoked.  Java handles such things by encapsulating the stack state, but D does not (for a variety of reasons). One way to resolve it is to change the approach such that MenuArgs becomes part of an enclosing class or struct around the handler, or otherwise becomes reachable from the handler (such as a static MenuArgs would be).

Which examples are you referring to, Kyle? I ask because there's a couple of subtle concerns here.


February 08, 2006
Kris wrote:
> "Kyle Furlong" <kylefurlong@gmail.com> wrote ..
> [snip]
>> Is this a bug? Or a feature?
> 
> 
> I suspect what's happening is that your out-of-scope MenuArgs are actually on the stack when you call handleMouseDown(), which is not the case when the delegate is invoked.  Java handles such things by encapsulating the stack state, but D does not (for a variety of reasons). One way to resolve it is to change the approach such that MenuArgs becomes part of an enclosing class or struct around the handler, or otherwise becomes reachable from the handler (such as a static MenuArgs would be).
> 
> Which examples are you referring to, Kyle? I ask because there's a couple of subtle concerns here. 
> 
> 

I guess I am just searching for best practices. If someone can come up with The Right Way to handle events in DWT I would be happy.

The examples I was referring to are the ones in the DWT distribution.
February 08, 2006
It's not a bug. It is a tradeoff.

I spent some time to integrate D delegate to DWT. And eventually made it
possible to support both D Delegate and Java like Listener to handle an
event;
Coexistence of delegate and listener can benefit port exists java project
which
use listener. And new app can use either as suitable; The passed arguments
makes it possible to use anonymous delegate.

But anonymous delegate can not access stack object or event part of an enclosing class/struct. This is because the install of delegate and invoke the delegate occurs in different stack.

Anonymous listener can access variable of the enclosing class, but seems can't access the enclosing class this pointer ( not sure )


assumed we have the class with Label and Menu variable
# class SomeClass {
# Label label;
# Menu menu;
# .....
# }


1) use delegate
  a) pass args as Kyle expressed, which is anonymous delegate
  b) use named delegate

# void foo(MouseEvent e) {
# // Do things with Label and Menu
# }
# label.handleMouseDown(null, &foo);


2) use listener

a) implement the listener interface by the class
# class SomeClass : SelectionListener {
# // implement the interface
# public void widgetSelected(SelectionEvent e){
# // Do things with Label and Menu
# }
# // install the listener
# label.addSelectionListener(this);
# }

b) create separated Listener class
Can be a separated class or inner class of the outer,
but still need pass the arguments in.
I am not sure whether inner class can access outer
class's member as Java does.

# class MyListener : SelectionListener {
# MenuArgs args;
# public this(MenuArgs args) { this.args = args; }
# public void widgetSelected(SelectionEvent e){
# // do things with args
# }

 c) anonymous listener
zwang gives an example in "sortindicator.d"
http://trac.dsource.org/projects/dwt/browser/trunk/current/win32/packages/dwt/examples/sortindicator/sortindicator.d?rev=96#L80



"Kyle Furlong" <kylefurlong@gmail.com> says:dsb732$44v$1@digitaldaemon.com...
> Currently, one has to write code like this:
>
> private class MenuArgs
> {
> Menu menu;
> Label label;
> this(Menu m, Label l)
> {
> menu = m;
> label = l;
> }
> }
>
> MenuArgs args = new MenuArgs(Menu, Label);
>
> Label.handleMouseDown(args, delegate void(MouseEvent e)
> {
> MenuArgs args = cast(MenuArgs)e.cData;
> // Do things with args.
> });
>
> But NOT like this:
>
> Label.handleMouseDown(null, delegate void(MouseEvent e)
> {
> // Do things with Label and Menu, and any other objects outside this
> scope.
> });
>
> Doing anything with objects outside of the scope of the delegate will cause AccessViolations inside of the DWT eventable.d, unless they are passed as cData.
>
> This seems to be an onerous restriction, and also counterintuitive. Also, all the examples use objects outside the scope of the delegate as well, so that it would seem to be The Right Way, except that it doesnt work.
>
>
> Is this a bug? Or a feature?