digitalmars.D.dwt - DWT event handling
- Frank Benoit (8/8) May 17 2008 I added the template function Bill suggested once to the
- bobef (3/16) May 18 2008 void handleTextEvent (Event e, Composite composite, TreeItem item, TreeE...
- Frank Benoit (33/36) May 18 2008 No, the additional arguments make the delegate a closure. If you would
- Lester L. Martin II (3/47) May 18 2008 In our code we just created a class that accepted a delegate. This class...
- bobef (2/53) May 18 2008 This was basically my point too. This way seems shorter than having to w...
- Frank Benoit (8/61) May 18 2008 The current code that look like this:
- Lester L. Martin II (31/97) May 18 2008 my code is more simple
- Frank Benoit (12/48) May 18 2008 I think this is just less flexible.
- Lester L. Martin II (3/59) May 18 2008 the delegate has to point to something; you cant call null(Event e); so ...
- BLS (38/54) May 18 2008 Hi Frank, thanks for the update !
- Bill Baxter (3/70) May 18 2008 I don't get it. What's 5?
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
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
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
Frank Benoit Wrote:bobef schrieb: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 IIvoid 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
Lester L. Martin II Wrote:Frank Benoit Wrote:This was basically my point too. This way seems shorter than having to write all these arguments and having to remember them :)bobef schrieb: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 IIvoid 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
bobef schrieb:Lester L. Martin II Wrote: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?Frank Benoit Wrote:This was basically my point too. This way seems shorter than having to write all these arguments and having to remember them :)bobef schrieb: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 IIvoid 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
Frank Benoit Wrote:bobef 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 }Lester L. Martin II Wrote: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?Frank Benoit Wrote:This was basically my point too. This way seems shorter than having to write all these arguments and having to remember them :)bobef schrieb: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 IIvoid 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
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
Frank Benoit Wrote:Lester L. Martin II schrieb: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 IImy 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
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. FrankHi 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
BLS wrote:Frank Benoit schrieb:I don't get it. What's 5? --bbI 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. FrankHi 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
Bill Baxter schrieb:BLS wrote: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 ...... BjoernFrank Benoit schrieb:I don't get it. What's 5? --bbI 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. FrankHi 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 19 2008
Sorry! just had a closer look at the DWT event-handling. My snippet is off topic. Bjoern (ashamed)
May 19 2008