www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.dwt - DWT event handling

reply Frank Benoit <keinfarbton googlemail.com> writes:
I added the template function Bill suggested once to the 
dwt.widgets.Listener module.

http://www.dsource.org/projects/dwt-linux/browser/dwt/widgets/Listener.d?rev=243%3A84629474b5ec

You can see that in action in this snippet
http://www.dsource.org/projects/dwt-samples/browser/snippets/treeeditor/Snippet111.d?rev=85%3Afa286c85e7b8

See lines: 102..106

Thanks Bill for the snippets and for this cool template function suggestion.

Frank
May 17 2008
next sibling parent reply bobef <bobef nospam-abv.bg> writes:
void handleTextEvent (Event e, Composite composite, TreeItem item, TreeEditor
editor,Text text, int inset ) 

This is longer to write than new class {blah blah} :)

Frank Benoit Wrote:

 I added the template function Bill suggested once to the 
 dwt.widgets.Listener module.
 
 http://www.dsource.org/projects/dwt-linux/browser/dwt/widgets/Listener.d?rev=243%3A84629474b5ec
 
 You can see that in action in this snippet
 http://www.dsource.org/projects/dwt-samples/browser/snippets/treeeditor/Snippet111.d?rev=85%3Afa286c85e7b8
 
 See lines: 102..106
 
 Thanks Bill for the snippets and for this cool template function suggestion.
 
 Frank

May 18 2008
parent reply Frank Benoit <keinfarbton googlemail.com> writes:
bobef schrieb:
 void handleTextEvent (Event e, Composite composite, TreeItem item, TreeEditor
editor,Text text, int inset ) 
 
 This is longer to write than new class {blah blah} :)

No, the additional arguments make the delegate a closure. If you would write that as a anonymous class it would look like that: In Java final vars are accessible for the anonymous class after the surrounding method ends: final Text text = ... final TreeEditor editor = ... Listener l = new Listener { public void handleEvent( Event e ){ // use text, editor as you want } } In D1, this would create crashes. The workaround is, to create explicit member variable in the anonymous class. This is really ugly and very tedious and error-prone. Listener l = new class( composite, item, editor, text, inset ) Listener { Composite composite_; TreeEditor editor_; Text text_; int inset_; public this( Composite a, TreeItem b, TreeEditor c,Text d, int e ) { this.composite_ = a; this.editor_ = b; this.text_ = d; this.inset_ = e; } public void handleEvent( Event e ){ // use the test_, editor_ ... // underscore to clearly separate them from // the variable used in the surounding method } } Now you see what is the advantage of the dgListener?
May 18 2008
parent reply Lester L. Martin II <lestermartin92 gmail.com> writes:
Frank Benoit Wrote:

 bobef schrieb:
 void handleTextEvent (Event e, Composite composite, TreeItem item, TreeEditor
editor,Text text, int inset ) 
 
 This is longer to write than new class {blah blah} :)

No, the additional arguments make the delegate a closure. If you would write that as a anonymous class it would look like that: In Java final vars are accessible for the anonymous class after the surrounding method ends: final Text text = ... final TreeEditor editor = ... Listener l = new Listener { public void handleEvent( Event e ){ // use text, editor as you want } } In D1, this would create crashes. The workaround is, to create explicit member variable in the anonymous class. This is really ugly and very tedious and error-prone. Listener l = new class( composite, item, editor, text, inset ) Listener { Composite composite_; TreeEditor editor_; Text text_; int inset_; public this( Composite a, TreeItem b, TreeEditor c,Text d, int e ) { this.composite_ = a; this.editor_ = b; this.text_ = d; this.inset_ = e; } public void handleEvent( Event e ){ // use the test_, editor_ ... // underscore to clearly separate them from // the variable used in the surounding method } } Now you see what is the advantage of the dgListener?

In our code we just created a class that accepted a delegate. This class inherited Listener. It defined a generic event handler that it would use if no event delegate was passed to it. What are the advantages of this template over such a design (If you need real code will post). Lester L. Martin II
May 18 2008
parent reply bobef <bobef nospam-abv.bg> writes:
Lester L. Martin II Wrote:

 Frank Benoit Wrote:
 
 bobef schrieb:
 void handleTextEvent (Event e, Composite composite, TreeItem item, TreeEditor
editor,Text text, int inset ) 
 
 This is longer to write than new class {blah blah} :)

No, the additional arguments make the delegate a closure. If you would write that as a anonymous class it would look like that: In Java final vars are accessible for the anonymous class after the surrounding method ends: final Text text = ... final TreeEditor editor = ... Listener l = new Listener { public void handleEvent( Event e ){ // use text, editor as you want } } In D1, this would create crashes. The workaround is, to create explicit member variable in the anonymous class. This is really ugly and very tedious and error-prone. Listener l = new class( composite, item, editor, text, inset ) Listener { Composite composite_; TreeEditor editor_; Text text_; int inset_; public this( Composite a, TreeItem b, TreeEditor c,Text d, int e ) { this.composite_ = a; this.editor_ = b; this.text_ = d; this.inset_ = e; } public void handleEvent( Event e ){ // use the test_, editor_ ... // underscore to clearly separate them from // the variable used in the surounding method } } Now you see what is the advantage of the dgListener?

In our code we just created a class that accepted a delegate. This class inherited Listener. It defined a generic event handler that it would use if no event delegate was passed to it. What are the advantages of this template over such a design (If you need real code will post). Lester L. Martin II

This was basically my point too. This way seems shorter than having to write all these arguments and having to remember them :)
May 18 2008
parent reply Frank Benoit <keinfarbton googlemail.com> writes:
bobef schrieb:
 Lester L. Martin II Wrote:
 
 Frank Benoit Wrote:

 bobef schrieb:
 void handleTextEvent (Event e, Composite composite, TreeItem item, TreeEditor
editor,Text text, int inset ) 

 This is longer to write than new class {blah blah} :)

write that as a anonymous class it would look like that: In Java final vars are accessible for the anonymous class after the surrounding method ends: final Text text = ... final TreeEditor editor = ... Listener l = new Listener { public void handleEvent( Event e ){ // use text, editor as you want } } In D1, this would create crashes. The workaround is, to create explicit member variable in the anonymous class. This is really ugly and very tedious and error-prone. Listener l = new class( composite, item, editor, text, inset ) Listener { Composite composite_; TreeEditor editor_; Text text_; int inset_; public this( Composite a, TreeItem b, TreeEditor c,Text d, int e ) { this.composite_ = a; this.editor_ = b; this.text_ = d; this.inset_ = e; } public void handleEvent( Event e ){ // use the test_, editor_ ... // underscore to clearly separate them from // the variable used in the surounding method } } Now you see what is the advantage of the dgListener?

Lester L. Martin II

This was basically my point too. This way seems shorter than having to write all these arguments and having to remember them :)

The current code that look like this: void handleMyEvent( Event e /+optional args follow+/, int myval ){ } addListener( DWT.Selection, dgListener( &handleMyEvent, avalue )); What happends, that the function dgListener does create a Listener class, and the handleEvent is forwareded to your supplied delegate. What am i missing?
May 18 2008
parent reply Lester L. Martin II <lestermartin92 gmail.com> writes:
Frank Benoit Wrote:

 bobef schrieb:
 Lester L. Martin II Wrote:
 
 Frank Benoit Wrote:

 bobef schrieb:
 void handleTextEvent (Event e, Composite composite, TreeItem item, TreeEditor
editor,Text text, int inset ) 

 This is longer to write than new class {blah blah} :)

write that as a anonymous class it would look like that: In Java final vars are accessible for the anonymous class after the surrounding method ends: final Text text = ... final TreeEditor editor = ... Listener l = new Listener { public void handleEvent( Event e ){ // use text, editor as you want } } In D1, this would create crashes. The workaround is, to create explicit member variable in the anonymous class. This is really ugly and very tedious and error-prone. Listener l = new class( composite, item, editor, text, inset ) Listener { Composite composite_; TreeEditor editor_; Text text_; int inset_; public this( Composite a, TreeItem b, TreeEditor c,Text d, int e ) { this.composite_ = a; this.editor_ = b; this.text_ = d; this.inset_ = e; } public void handleEvent( Event e ){ // use the test_, editor_ ... // underscore to clearly separate them from // the variable used in the surounding method } } Now you see what is the advantage of the dgListener?

Lester L. Martin II

This was basically my point too. This way seems shorter than having to write all these arguments and having to remember them :)

The current code that look like this: void handleMyEvent( Event e /+optional args follow+/, int myval ){ } addListener( DWT.Selection, dgListener( &handleMyEvent, avalue )); What happends, that the function dgListener does create a Listener class, and the handleEvent is forwareded to your supplied delegate. What am i missing?

my code is more simple class listen: Listener { void delegate(Event e) func_; this(void delegate(Event e) func = null) { if(func !is null) func_ = func; else func_ = &this.genericHandle; } public void handleEvent(Event e) { func_(e); } public void genericHandle(Event e) { Stdout("Event Accepted.").newline.flush; } } (user is a declared DWT variable) user.addListener(new listen(&dg)); (this is a function inside a class) private void dg(Event E) { //handle event here }
May 18 2008
parent reply Frank Benoit <keinfarbton googlemail.com> writes:
Lester L. Martin II schrieb:
 my code is more simple
 
 class listen: Listener
     {
         void delegate(Event e) func_;
         
         this(void delegate(Event e) func = null)
         {
             if(func !is null)
                 func_ = func;
             else
                 func_ = &this.genericHandle;
         }
         
         public void handleEvent(Event e) 
         { 
             func_(e); 
         }
         
         public void genericHandle(Event e)
         {
             Stdout("Event Accepted.").newline.flush;
         }
     }
 
 (user is a declared DWT variable)
 
 user.addListener(new listen(&dg));
 
 (this is a function inside a class)
 
 private void dg(Event E)
 {
     //handle event here
 }
 

I think this is just less flexible. This simple case would be: user.addListener(dgListener(&dg)); private void dg(Event E) { //handle event here } It is the same. But the template can handle _optional_ arguments that are stored in a generated template class. Well actually there is no default-handler. But i do not understand what is the use of that. If you do not want a handler, why register a dummy one?
May 18 2008
parent Lester L. Martin II <lestermartin92 gmail.com> writes:
Frank Benoit Wrote:

 Lester L. Martin II schrieb:
 my code is more simple
 
 class listen: Listener
     {
         void delegate(Event e) func_;
         
         this(void delegate(Event e) func = null)
         {
             if(func !is null)
                 func_ = func;
             else
                 func_ = &this.genericHandle;
         }
         
         public void handleEvent(Event e) 
         { 
             func_(e); 
         }
         
         public void genericHandle(Event e)
         {
             Stdout("Event Accepted.").newline.flush;
         }
     }
 
 (user is a declared DWT variable)
 
 user.addListener(new listen(&dg));
 
 (this is a function inside a class)
 
 private void dg(Event E)
 {
     //handle event here
 }
 

I think this is just less flexible. This simple case would be: user.addListener(dgListener(&dg)); private void dg(Event E) { //handle event here } It is the same. But the template can handle _optional_ arguments that are stored in a generated template class. Well actually there is no default-handler. But i do not understand what is the use of that. If you do not want a handler, why register a dummy one?

the delegate has to point to something; you cant call null(Event e); so I set it to a default one that matches our projects needs. I didn't say that it would have to be exactly like that but to us it is Flexible enought at the moment to accomplish everything we need. Extending the class to match your template and be just as flexible shouldn't be too hard (but then I'm not the one who's good at DWT, it's my friend who does that code). Lester L. Martin II
May 18 2008
prev sibling parent reply BLS <nanali nospam-wanadoo.fr> writes:
Frank Benoit schrieb:
 I added the template function Bill suggested once to the 
 dwt.widgets.Listener module.
 
 http://www.dsource.org/projects/dwt-linux/browser/dwt/widgets/Listener.d?re
=243%3A84629474b5ec 
 
 
 You can see that in action in this snippet
 http://www.dsource.org/projects/dwt-samples/browser/snippets/treeeditor/Snippet111.d?r
v=85%3Afa286c85e7b8 
 
 
 See lines: 102..106
 
 Thanks Bill for the snippets and for this cool template function 
 suggestion.
 
 Frank

Hi Frank, thanks for the update ! I still try to figure out how this code could fit ... template MessageMap(Mappings ...) { void addListener(uint uID) { foreach(mapping; Mappings) { if(mapping.matches(uID)) // DWTxxxx mapping.executeAction(); } } } //maybe we need template specialisation here ??? struct OnClose(alias fn) { alias fn executeAction; static bool matches(uint uid) { return uid == 5; } } struct OnRange(uint a, uint b, alias fn) { alias fn executeAction; static bool matches(uint uid) { return uid >= a && uid <= b; } } class Foo { void foo() { writefln("foo called"); } void bar() { writefln("bar called"); } mixin MessageMap!( OnClose!(foo), OnRange!(1, 3, bar) ); } void main() { auto f = new Foo; f.addListener(5); f.addListener(2); } At least it looks simpler (to me) Ideas ? Bjoern
May 18 2008
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
BLS wrote:
 Frank Benoit schrieb:
 I added the template function Bill suggested once to the 
 dwt.widgets.Listener module.

 http://www.dsource.org/projects/dwt-linux/browser/dwt/widgets/Listener.d?re
=243%3A84629474b5ec 


 You can see that in action in this snippet
 http://www.dsource.org/projects/dwt-samples/browser/snippets/treeeditor/Snippet111.d?r
v=85%3Afa286c85e7b8 


 See lines: 102..106

 Thanks Bill for the snippets and for this cool template function 
 suggestion.

 Frank

Hi Frank, thanks for the update ! I still try to figure out how this code could fit ... template MessageMap(Mappings ...) { void addListener(uint uID) { foreach(mapping; Mappings) { if(mapping.matches(uID)) // DWTxxxx mapping.executeAction(); } } } //maybe we need template specialisation here ??? struct OnClose(alias fn) { alias fn executeAction; static bool matches(uint uid) { return uid == 5; } } struct OnRange(uint a, uint b, alias fn) { alias fn executeAction; static bool matches(uint uid) { return uid >= a && uid <= b; } } class Foo { void foo() { writefln("foo called"); } void bar() { writefln("bar called"); } mixin MessageMap!( OnClose!(foo), OnRange!(1, 3, bar) ); } void main() { auto f = new Foo; f.addListener(5); f.addListener(2); } At least it looks simpler (to me) Ideas ? Bjoern

I don't get it. What's 5? --bb
May 18 2008
parent reply BLS <nanali nospam-wanadoo.fr> writes:
Bill Baxter schrieb:
 BLS wrote:
 Frank Benoit schrieb:
 I added the template function Bill suggested once to the 
 dwt.widgets.Listener module.

 http://www.dsource.org/projects/dwt-linux/browser/dwt/widgets/Listener.d?re
=243%3A84629474b5ec 


 You can see that in action in this snippet
 http://www.dsource.org/projects/dwt-samples/browser/snippets/treeeditor/Snippet111.d?r
v=85%3Afa286c85e7b8 


 See lines: 102..106

 Thanks Bill for the snippets and for this cool template function 
 suggestion.

 Frank

Hi Frank, thanks for the update ! I still try to figure out how this code could fit ... template MessageMap(Mappings ...) { void addListener(uint uID) { foreach(mapping; Mappings) { if(mapping.matches(uID)) // DWTxxxx mapping.executeAction(); } } } //maybe we need template specialisation here ??? struct OnClose(alias fn) { alias fn executeAction; static bool matches(uint uid) { return uid == 5; } } struct OnRange(uint a, uint b, alias fn) { alias fn executeAction; static bool matches(uint uid) { return uid >= a && uid <= b; } } class Foo { void foo() { writefln("foo called"); } void bar() { writefln("bar called"); } mixin MessageMap!( OnClose!(foo), OnRange!(1, 3, bar) ); } void main() { auto f = new Foo; f.addListener(5); f.addListener(2); } At least it looks simpler (to me) Ideas ? Bjoern

I don't get it. What's 5? --bb

I wrote the first reply before I had my first coffee. Bad idea :) A better, annotated sample : template MessageMap(Mappings ...) { void addListener(uint uID) { foreach(mapping; Mappings) { if(mapping.matches(uID)) // DWTxxxx mapping.executeAction(); } } } /* Defining a few templated structs. The structs (not instances of them, the actual type!) are given to MessageMap which calls the *static* function(s). So technically, OnFocusOut!(FocusOut) and OnRange!(1, 3, Range) are *types* that contain aliases (think of compile time references) to the methods you want to call. */ struct OnFocusOut(alias fn) { alias fn executeAction; static bool matches(uint uid) { return uid == DWT.FocusOut; } } // just an other sample struct OnRange(uint a, uint b, alias fn) { alias fn executeAction; static bool matches(uint uid) { return uid >= a && uid <= b; } } class Window { void FocusOut() { writefln("DWT.FocusOut event"); } void Range() { writefln("OnRange called"); } mixin MessageMap!( OnFocusOut!(FocusOut), OnRange!(1, 3, Range) ); /* This mixin expands to : void addListener(uint uID) { foreach(mapping; Mappings) { //loops 2 times -> see Mixin if(mapping.matches(uID)) //just like "if (uID == DWT.FocusOut)" mapping.executeAction(); //calls alias fn -> see structs } } } The "mixin MessageMap!(...)" simply adds a new method to your class. Note that because it is run over types, the "foreach(mapping; Mappings) { .. }" is done at compile time, ie its body is repeated for every type (I called them Mapping's here), so all runtime overhead you have are the ifs that evaluate to false. */ void main() { auto w = new Window; w.addListener(DWT.FocusOut); w.addListener(DWT.WhatEver); } This is an attemp to create something similar to MFCs BEGIN_MESSAGE_MAP / END_MESSAGE_MAP I am NOT sure how this snippet could fit into DWTs event management. It is just an idea. :( Finally : I guess template specialisation seems to be neessesary to support events that return a value ...... Bjoern
May 19 2008
parent BLS <nanali nospam-wanadoo.fr> writes:
Sorry! just had a closer look at the DWT event-handling.
My snippet is off topic.
Bjoern (ashamed)
May 19 2008