Thread overview
Event handling
Mar 21, 2008
Frank Benoit
Mar 28, 2008
bobef
Apr 09, 2008
Bill Baxter
Apr 13, 2008
Frank Benoit
Apr 13, 2008
Bjoern
Apr 13, 2008
Frank Benoit
Apr 14, 2008
Bill Baxter
March 21, 2008
I think about how to do the event handling more D like, but also to avoid adding/changing code in the ported code.

The dwt from Shawn made this possible:

table.addListener(
	DWT.Selection,
	&myHandler,
	&myData
	);

+ use of delegates
+ optionally add data that is passed to the delegate
- data must an "Object"
- adds code into the dwt

Now i think about adding this new class template to dwt.widgets.Listener:

/// start of addition to dwt.widgets.Listener
class DgListenerT( T... ) : Listener {
    alias void delegate(Event, T) ADel;
    ADel dg;
    T t;
    public this( ADel dg, T t ){
        this.dg = dg;
        this.t = t;
    }
    public void handleEvent( Event e ){
        dg(e, t);
    }
}
alias DgListenerT!() DgListener;
/// end of addition to dwt.widgets.Listener


table.addListener(
	DWT.Selection,
	new DgListener( &myHandler )
	);
table.addListener(
	DWT.Selection,
	new DgListenerT!( int )( &myHandler, 23 )
	);

+ use of delegates
+ optionally add data that is passed to the delegate
+ data count and types are not fix
+ adds only additional class outside existing classes
+ no dwt internals need to be changed and maintained
- need heap allocate the DgListenerT instance

Are there more arguments pro/cons?
Would you prefer another solution?
March 28, 2008
Maybe you could use opCall to make things shorter to write?

Frank Benoit Wrote:

> I think about how to do the event handling more D like, but also to avoid adding/changing code in the ported code.
> 
> The dwt from Shawn made this possible:
> 
> table.addListener(
> 	DWT.Selection,
> 	&myHandler,
> 	&myData
> 	);
> 
> + use of delegates
> + optionally add data that is passed to the delegate
> - data must an "Object"
> - adds code into the dwt
> 
> Now i think about adding this new class template to dwt.widgets.Listener:
> 
> /// start of addition to dwt.widgets.Listener
> class DgListenerT( T... ) : Listener {
>      alias void delegate(Event, T) ADel;
>      ADel dg;
>      T t;
>      public this( ADel dg, T t ){
>          this.dg = dg;
>          this.t = t;
>      }
>      public void handleEvent( Event e ){
>          dg(e, t);
>      }
> }
> alias DgListenerT!() DgListener;
> /// end of addition to dwt.widgets.Listener
> 
> 
> table.addListener(
> 	DWT.Selection,
> 	new DgListener( &myHandler )
> 	);
> table.addListener(
> 	DWT.Selection,
> 	new DgListenerT!( int )( &myHandler, 23 )
> 	);
> 
> + use of delegates
> + optionally add data that is passed to the delegate
> + data count and types are not fix
> + adds only additional class outside existing classes
> + no dwt internals need to be changed and maintained
> - need heap allocate the DgListenerT instance
> 
> Are there more arguments pro/cons?
> Would you prefer another solution?

April 09, 2008
Frank Benoit wrote:
> I think about how to do the event handling more D like, but also to avoid adding/changing code in the ported code.
> 
> The dwt from Shawn made this possible:
> 
> table.addListener(
>     DWT.Selection,
>     &myHandler,
>     &myData
>     );
> 
> + use of delegates
> + optionally add data that is passed to the delegate
> - data must an "Object"
> - adds code into the dwt
> 
> Now i think about adding this new class template to dwt.widgets.Listener:
> 
> /// start of addition to dwt.widgets.Listener
> class DgListenerT( T... ) : Listener {
>     alias void delegate(Event, T) ADel;
>     ADel dg;
>     T t;
>     public this( ADel dg, T t ){
>         this.dg = dg;
>         this.t = t;
>     }
>     public void handleEvent( Event e ){
>         dg(e, t);
>     }
> }
> alias DgListenerT!() DgListener;
> /// end of addition to dwt.widgets.Listener
> 
> 
> table.addListener(
>     DWT.Selection,
>     new DgListener( &myHandler )
>     );
> table.addListener(
>     DWT.Selection,
>     new DgListenerT!( int )( &myHandler, 23 )
>     );
> 
> + use of delegates
> + optionally add data that is passed to the delegate
> + data count and types are not fix
> + adds only additional class outside existing classes
> + no dwt internals need to be changed and maintained
> - need heap allocate the DgListenerT instance
> 
> Are there more arguments pro/cons?
> Would you prefer another solution?


Here's a spin on that idea that allows the delegate to take an Event parameter, or not, as it wishes.  This one uses a factory function, which I think is the way to go, because that enables IFTI for the parameter types.



----
import std.traits;

template Tuple(T...) { alias T Tuple; }

/// A listener that takes a delegate.  The Event arg is optional
class _DgListenerT(Dg, T... ) : Listener {
    alias ParameterTypeTuple!(Dg) DgArgs;
    static assert( is(DgArgs == T)
                   || is(DgArgs == Tuple!(Event,T)),
                   "Delegate args not correct" );
    Dg dg;
    T t;
    this( Dg dg, T t )
    {
        this.dg = dg;
        static if (T.length > 0) {
            this.t = t;
        }
    }
    void handleEvent( Event e ){
        static if (is(typeof(dg(e,t)))) {
            dg(e, t);
        }
        else static if (is(typeof(dg(t)))) {
            dg(t);
        }
        else {
            static assert(false, "Delegate type is incorrect for arguments supplied");
        }
    }
}


_DgListenerT!(Dg,T)
DgListener(Dg, T...)(Dg dg, T args)
{
    return new _DgListenerT!(Dg,T)(dg,args);
}
April 13, 2008
Bill Baxter schrieb:
> Here's a spin on that idea that allows the delegate to take an Event parameter, or not, as it wishes.  This one uses a factory function, which I think is the way to go, because that enables IFTI for the parameter types.
> 
> ....

I added this for an jface example.
See:

http://www.dsource.org/projects/dwt-addons/browser/dwtx/jface/operation/IRunnableWithProgress.d?rev=57%3A89776a9bb8b2

http://www.dsource.org/projects/dwt-samples/changeset/72%3Afc7a8f537871


April 13, 2008
Bill Baxter schrieb:
> Frank Benoit wrote:
>> I think about how to do the event handling more D like, but also to avoid adding/changing code in the ported code.
>>
>> The dwt from Shawn made this possible:
>>
>> table.addListener(
>>     DWT.Selection,
>>     &myHandler,
>>     &myData
>>     );
>>
>> + use of delegates
>> + optionally add data that is passed to the delegate
>> - data must an "Object"
>> - adds code into the dwt
>>
>> Now i think about adding this new class template to dwt.widgets.Listener:
>>
>> /// start of addition to dwt.widgets.Listener
>> class DgListenerT( T... ) : Listener {
>>     alias void delegate(Event, T) ADel;
>>     ADel dg;
>>     T t;
>>     public this( ADel dg, T t ){
>>         this.dg = dg;
>>         this.t = t;
>>     }
>>     public void handleEvent( Event e ){
>>         dg(e, t);
>>     }
>> }
>> alias DgListenerT!() DgListener;
>> /// end of addition to dwt.widgets.Listener
>>
>>
>> table.addListener(
>>     DWT.Selection,
>>     new DgListener( &myHandler )
>>     );
>> table.addListener(
>>     DWT.Selection,
>>     new DgListenerT!( int )( &myHandler, 23 )
>>     );
>>
>> + use of delegates
>> + optionally add data that is passed to the delegate
>> + data count and types are not fix
>> + adds only additional class outside existing classes
>> + no dwt internals need to be changed and maintained
>> - need heap allocate the DgListenerT instance
>>
>> Are there more arguments pro/cons?
>> Would you prefer another solution?
> 
> 
> Here's a spin on that idea that allows the delegate to take an Event parameter, or not, as it wishes.  This one uses a factory function, which I think is the way to go, because that enables IFTI for the parameter types.
> 
> 
> 
> ----
> import std.traits;
> 
> template Tuple(T...) { alias T Tuple; }
> 
> /// A listener that takes a delegate.  The Event arg is optional
> class _DgListenerT(Dg, T... ) : Listener {
>     alias ParameterTypeTuple!(Dg) DgArgs;
>     static assert( is(DgArgs == T)
>                    || is(DgArgs == Tuple!(Event,T)),
>                    "Delegate args not correct" );
>     Dg dg;
>     T t;
>     this( Dg dg, T t )
>     {
>         this.dg = dg;
>         static if (T.length > 0) {
>             this.t = t;
>         }
>     }
>     void handleEvent( Event e ){
>         static if (is(typeof(dg(e,t)))) {
>             dg(e, t);
>         }
>         else static if (is(typeof(dg(t)))) {
>             dg(t);
>         }
>         else {
>             static assert(false, "Delegate type is incorrect for arguments supplied");
>         }
>     }
> }
> 
> 
> _DgListenerT!(Dg,T)
> DgListener(Dg, T...)(Dg dg, T args)
> {
>     return new _DgListenerT!(Dg,T)(dg,args);
> }

Is such a hack really nessesary ? ( ... Sorry ... )

I mean A look at old school Smalltalk's  message handling should teach us that "code blocks" // in our D case : closures // enable us to find a
smarter solution. So I vote for spending  a reasonable amount of time to figure out either a good/better D-ish solution or give a smalltalk like solution a try.

Just my unholy opinion / the current DWT event handling is a bit clumbsy.
->
Well, Closures are a D2 feature . and implementing code blocks using closures is not very smart .. THough I'm  conviced that a closure based solution is worth thinking twice...

OT ---------------------------------------
D blocks : Pseudo code
------------------------------------------
for_each = function (list, block)
{
for (i = 0; i < list.sizeof(); ++i)
block(list[i])
}

list = #(12, 34, 56) // tuple
for_each(list)
{ |x| Print(x) }

=>  12
34
56
April 13, 2008
Bjoern schrieb:
> Is such a hack really nessesary ? ( ... Sorry ... )
> 
> I mean A look at old school Smalltalk's  message handling should teach us that "code blocks" // in our D case : closures // enable us to find a
> smarter solution. So I vote for spending  a reasonable amount of time to figure out either a good/better D-ish solution or give a smalltalk like solution a try.
> 
> Just my unholy opinion / the current DWT event handling is a bit clumbsy.
> ->
> Well, Closures are a D2 feature . and implementing code blocks using closures is not very smart .. THough I'm  conviced that a closure based solution is worth thinking twice...
> 
> OT ---------------------------------------
> D blocks : Pseudo code
> ------------------------------------------
> for_each = function (list, block)
> {
> for (i = 0; i < list.sizeof(); ++i)
> block(list[i])
> }
> 
> list = #(12, 34, 56) // tuple
> for_each(list)
> { |x| Print(x) }
> 
> =>  12
> 34
> 56

I don't get what your example shall illustrate.
Can you explain a bit more verbose?






April 14, 2008
Frank Benoit wrote:
> Bjoern schrieb:
>> Is such a hack really nessesary ? ( ... Sorry ... )
>>
>> I mean A look at old school Smalltalk's  message handling should teach us that "code blocks" // in our D case : closures // enable us to find a
>> smarter solution. So I vote for spending  a reasonable amount of time to figure out either a good/better D-ish solution or give a smalltalk like solution a try.
>>
>> Just my unholy opinion / the current DWT event handling is a bit clumbsy.
>> ->
>> Well, Closures are a D2 feature . and implementing code blocks using closures is not very smart .. THough I'm  conviced that a closure based solution is worth thinking twice...
>>
>> OT ---------------------------------------
>> D blocks : Pseudo code
>> ------------------------------------------
>> for_each = function (list, block)
>> {
>> for (i = 0; i < list.sizeof(); ++i)
>> block(list[i])
>> }
>>
>> list = #(12, 34, 56) // tuple
>> for_each(list)
>> { |x| Print(x) }
>>
>> =>  12
>> 34
>> 56
> 
> I don't get what your example shall illustrate.
> Can you explain a bit more verbose?

Bjoern, I don't really get what you're saying either, but it sounds vaguely like you're saying let's make delegates be usable as event handlers.

That's basically what this adapter template does.  It lets you say :

  setListener(dgWrapper(
     (Event ev) { Print(ev); }
  ));

Instead of:

  setListener(new class Listener {
     void handleEvent(Event ev) {
        Print(ev);
     }
  });

The next step would be to add an override to the setListener method to take a delegate and create the _DgListenerWrapperT automatically under the hood.  Then you could do:
  setListener(
    (Event ev) { Print(ev); }
  )

but that wouldn't allow passing the extra args.

--bb