Also, in "FocusWidget" class, clickListeners field is listed as ::
private ClickListenerCollection clickListeners; which means that every Button instance has its own set of of ClickListenerCollection, whereas (if I correctly decipher your post), javascript seems to create a static set of "ClickListenerCollection", which happens to be shared by all Button instances, and (assuming this is the case), the one-listener-paradigm clearly wins over a self- independent-listener-per-anonymous-class. However, I am not sure, and is driving me nuts as to how weird can this get, wherein an instance variable in Java is converted to a static variable in Javascript.. Looking forward to some potions of wisdom.. On Feb 4, 10:21 am, Ajay Garg <[email protected]> wrote: > But isn't Javascript "static" keyword, different from Java "static" > keyword ... In Javascript, it still regains object scope, while in > Java, it is a class scope .....?????? > > On Feb 3, 9:42 pm, gregor <[email protected]> wrote: > > > > > It's interesting to see how these various methods actually work in > > javascript. > > > In all cases click listeners are managed using the following methods. > > If you look at the basic Button constructor you can see it calls the > > addClickListener(..) function > > > function $addClickListener(this$static, listener){ > > if (!this$static.clickListeners) { > > this$static.clickListeners = $ClickListenerCollection(new > > ClickListenerCollection()); > > sinkEvents(this$static.element, 1 | (this > > $static.element.__eventBits || 0)); > > } > > $add_2(this$static.clickListeners, listener); > > > } > > > Then the user click is detected > > > function onBrowserEvent(event_0){ > > if ($eventGetTypeInt(event_0) == 1) { > > if (this.clickListeners) { > > $fireClick(this.clickListeners, this); > > } > > } > > > } > > > Then the elements with ClickListeners attached are queried to see if > > any match the element the user clicked. Obviously the more there are, > > the longer this will take. > > > function $fireClick(this$static, sender){ > > var listener, listener$iterator; > > for (listener$iterator = $AbstractList$IteratorImpl(new AbstractList > > $IteratorImpl(), this$static); listener$iterator.i < listener > > $iterator.this$0.size_0();) { > > listener = dynamicCast($next_0(listener$iterator), 5); > > $onClick(listener, sender); > > } > > > } > > > Now we can look at how three methods of setting up Buttons with > > ClickListsners is set up in javascript. > > > Method 1: A shared ClickListener - note using a hash table lookup > > would be much more efficient than this if there where a lot of > > them. > > > ClickListener buttonListener = new ClickListener() { > > public void onClick(Widget sender) { > > if (sender==sharedButtonOne) { > > Window.alert("Shared One"); > > return; > > } > > if (sender==sharedButtonTwo) { > > Window.alert("Shared Two"); > > return; > > } > > > } > > }; > > > Button sharedButtonOne = new Button("Shared 1",buttonListener); > > Button sharedButtonTwo = new Button("Shared 2",buttonListener); > > > This translates as follows. Note the single listener instance is > > translated to Sandbox$1 (my scratch module is called SandBox BTW). > > However many Buttons are added we will still have this single instance > > of it. > > > function $SandBox(this$static){ > > this$static.layout = $HorizontalPanel(new HorizontalPanel()); > > this$static.buttonListener = new SandBox$1(); > > this$static.sharedButtonOne = $Button_0(new Button(), 'Shared 1', > > this$static.buttonListener); > > this$static.sharedButtonTwo = $Button_0(new Button(), 'Shared 2', > > this$static.buttonListener); > > return this$static; > > > } > > > function $SandBox$1(this$static, this$0){ > > this$static.this$0 = this$0; > > return this$static; > > > } > > > function $onClick(this$static, sender){ > > if (sender == this$static.this$0.sharedButtonOne) { > > $wnd.alert('Shared One'); > > return; > > } > > if (sender == this$static.this$0.sharedButtonTwo) { > > $wnd.alert('Shared Two'); > > return; > > } > > > } > > > function SandBox$1(){ > > > } > > > _ = SandBox$1.prototype = new Object_0(); > > _.typeId$ = 23; > > _.this$0 = null; > > > Method 2: using anonymous inner class > > > Button innerButtonOne = new Button("Inner One", new ClickListener > > () { > > public void onClick(Widget sender) { > > Window.alert("Inner One"); > > } > > }); > > > Button innerButtonTwo = new Button("Inner Two", new ClickListener > > () { > > public void onClick(Widget sender) { > > Window.alert("Inner Two"); > > } > > }); > > > This translates as follows: Note that we now have two listener > > objects, both of which will be added to the main ClickListener > > collection. With 100 buttons, we would have 100 of them. > > > function $SandBox(this$static){ > > this$static.layout = $HorizontalPanel(new HorizontalPanel()); > > this$static.innerButtonOne = $Button_1(new Button(), 'Inner One', > > new SandBox$1()); > > this$static.innerButtonTwo = $Button_1(new Button(), 'Inner Two', > > new SandBox$2()); > > return this$static; > > > } > > > function onClick(sender){ > > $wnd.alert('Inner One'); > > > } > > > function SandBox$1(){ > > > } > > > _ = SandBox$1.prototype = new Object_0(); > > _.onClick = onClick; > > _.typeId$ = 23; > > function onClick_0(sender){ > > $wnd.alert('Inner Two'); > > > } > > > function SandBox$2(){ > > > } > > > _ = SandBox$2.prototype = new Object_0(); > > _.onClick = onClick_0; > > _.typeId$ = 24; > > > method 3: your EButton > > > EButton ajaysButtonOne = new EButton("Ajay's One") { > > public void onClick(Widget sender) { > > Window.alert("Ebutton 1"); > > } > > }; > > > EButton ajaysButtonTwo = new EButton("Ajay's Two") { > > public void onClick(Widget sender) { > > Window.alert("Ebutton 2"); > > } > > }; > > > This translates as follows: As you can see a separate instance (SandBox > > $1 & sandBox$2) created for each EButton instance. It appears to have > > basically turned itself into a ClickListener equivalent to method 2. > > It's instructive to compare this with how a normal Button is > > constructed in methods 1 & 2. > > > function $SandBox(this$static){ > > this$static.layout = $HorizontalPanel(new HorizontalPanel()); > > this$static.ajaysButtonOne = $SandBox$1(new SandBox$1(), "Ajay's > > One"); > > this$static.ajaysButtonTwo = $SandBox$2(new SandBox$2(), "Ajay's > > Two"); > > return this$static; > > > } > > > function $EButton(this$static, text){ > > $ButtonBase(this$static, $doc.createElement('button')); > > adjustType(this$static.element); > > this$static.element['className'] = 'gwt-Button'; > > $setInnerText(this$static.element, text); > > $addClickListener(this$static, this$static); > > return this$static; > > > } > > > function EButton(){ > > > } > > > _ = EButton.prototype = new Button(); > > _.typeId$ = 23; > > function $SandBox$1(this$static, $anonymous0){ > > $EButton(this$static, $anonymous0); > > return this$static; > > > } > > > function onClick(sender){ > > $wnd.alert('Ebutton 1'); > > > } > > > function SandBox$1(){ > > > } > > > _ = SandBox$1.prototype = new EButton(); > > _.onClick = onClick; > > _.typeId$ = 24; > > function $SandBox$2(this$static, $anonymous0){ > > $EButton(this$static, $anonymous0); > > return this$static; > > > } > > > function onClick_0(sender){ > > $wnd.alert('Ebutton 2'); > > > } > > > function SandBox$2(){ > > > } > > > _ = SandBox$2.prototype = new EButton(); > > _.onClick = onClick_0; > > _.typeId$ = 25; > > > So my reading of this is: > > > 1) All three methods involve creating a Button instance which > > translates into a native Button element provided by the browser and > > attached to the DOM. > > 2) All three methods involve creating one or more listener objects > > (sandBox$1, SandBox$2 etc) that are added to the static ClickListsner > > Collection > > 3) When a Click event is fired from the browser, the click listeners > > are queried to see if any are registered with the clicked DOM element. > > 4) In method one there is only one of them, so that question is > > answered very quickly > > 5) In methods 2 & 3, the more buttons there are, the longer this > > takes. > > 6) Although EButtons appear to register themselves with themselves > > ($addClickListener(this$static, this$static)) they still go through > > the same rigmarole through the listener collection if one is clicked - > > they do not bypass it by saying "oh, I can just call myself" as far as > > I can see. > > 7) The EButton option results in marginally more code than the inner > > class option, and massively more than the shared listener option > > (multiply it all up by e.g. 100), may run slower as a result even by > > comparison with the inner class option, and will certainly increase > > the size of the javascript files. > > 8) I think it demonstrates conclusively why using the single listener > > technique can make a huge difference if you have a large number of > > clickable widgets in an application. > > > On Feb 3, 8:14 am, Ajay Garg <[email protected]> wrote: > > > > Hmm.. I looked at GWT's code, and went all > > > thewayuptohttp://google-web-toolkit.googlecode.com/svn/javadoc/1.5/com/google/g... > > > code. > > > > Button is a sub-subclass of FocusWidget, and this is what happens. > > > Whenever a clickListener is added to a Button for the first time, > > > "Event.Click" event is sunk in for the newly instantiated Button > > > instance, and the clickListener added to ClickListenerCollection. > > > Next, whenever an onBrowserEvent(Event event) method is triggered, the > > > onClick() method is called for each of the clickListener registered in > > > ClickListenerCollection. > > > > So, as far as managing a large number of ClickListeners goes, if we go > > > by using EButton, the number of ClickListeners is equal to the number > > > of anonymous abstract classes made out of EButton. > > > > I think a more thinking point would be to consider "public void > > > sinkEvents(int eventBitsToAdd)" method of UIObject class, which > > > happens to be a superclass of FocusWidget. This method is called > > > whenever a ClickListener is added to an instance for the first time. > > > Thus, it does not matter whether the ClickListener interface being > > > added is the same reference as the anonymous abstract > > ... > > read more »- Hide quoted text - > > - Show quoted text - --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/Google-Web-Toolkit?hl=en -~----------~----~----~----~------~----~------~--~---
