www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.dwt - Event handling

reply Frank Benoit <keinfarbton googlemail.com> writes:
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?
Mar 21 2008
next sibling parent bobef <bobef abv-nospam.bg> writes:
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?

Mar 28 2008
prev sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
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); }
Apr 09 2008
next sibling parent Frank Benoit <keinfarbton googlemail.com> writes:
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
Apr 13 2008
prev sibling parent reply Bjoern <nanali nospam-wanadoo.fr> writes:
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
Apr 13 2008
parent reply Frank Benoit <keinfarbton googlemail.com> writes:
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?
Apr 13 2008
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
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
Apr 13 2008