In GWT 1.3 I could have a Widget that responded to browser events from
elements other than the widget's top level element. Eg: A table Widget
that sinks events on it's <td> elements represented by UIObjects.
In GWT 1.4.10RC it seems I have to sinkEvents on the top level element
of the widget or it won't receive any browser events. eg: sinkEvents
on the <table> element.
Is this an intentional change? Being that sinkEvents is on UIObject
instead of Widget, this seems to not be the intended behavior or an
unfortunate place for the sinkEvents method to be.
--
Sandy McArthur
"He who dares not offend cannot be honest."
- Thomas Paine
Then it is most unfortunate and counter intuitive that the sinkEvents
method is part of the UIObject class and not the Widget class if that
is the only place it works.
> However, I do understand what you mean about the negative performance impact
> of having to call sinkEvents on the entire Table widget when you only care
> about events on the <td> itself.
>
> One way to get around this problem would be to call DOM.setEventListener(td,
> tableWidget). That way, the <td> element would pick up events, and the Table
> widget would act as the listener. However, to prevent memory leaks, you
> would have to make sure to clear this event listener when the Table widget
> becomes detached from the DOM.
Which is why I had rationalized/accepted the counter intuitiveness of
registering for events you care about on UIObjects (DOM elements) but
processing them on the UIObject's parent Widget.
The "UIObject sends events to a parent Widget" design also makes
certain kind of sense if my suggestion for a future DnD interface was
that any UIObject could be a drag source/target. This way the whole or
just parts of a Widget could be drag grips or drop targets instead of
the whole Widget.
> If possible, can you describe some of the use cases in which you depend on
> the the existing event behavior in 1.3.3.?
This change will break behavior for anyone who uses GWT-Stuff's
ObjectListTable and needs to response to mouse events at the row group
or row level until either the old behavior is restored or I cut a new
GWT-Stuff release without any browser event handling optimizations.
The table widget from GWT-Stuff models the full w3c table model. The
Widget subclass is the table element with internally managed tbody,
thead, tfoot, and tr elements represented by various UIObject
subclasses. (The td and th elements are Panel subclasses.) The
UIObjects that make up the table row groups and rows call sinkEvents
the first time the programmer indicates they want to receive mouse
events for those row groups or rows (Table cells are handled just like
you would with a Panel).
Too see an example of how it can get slow, when I display a lot of
rows in the test app below on an older machine and move the mouse over
some rows the browser can take over a second to re-render the effect
of the mouse moving across the table. (The row group/rows colors are
updated via JavaScript and not CSS:hover.)
http://sandy.mcarthur.org/gwt-stuff/org.mcarthur.sandy.gwt.table.olt.TestObjectListTable/TestObjectListTable.html
I can deal with this behavior change and I already avoid huge complex
UI designs when I can but I'm kind of annoyed that I'll have to
revisit the ~4 days of spare time that I spent trying out event
processing optimizations and then benchmarking them to find an optimal
one again. :-/
> This fix was also meant to correct the behavior that you are taking
> advantage of. That is, it would be strange to call sinkEvents on a child
> <td>, and then receive events on the Table widget, when sinkEvents was
> never called on the Table widget to begin with.
Then it is most unfortunate and counter intuitive that the sinkEvents
method is part of the UIObject class and not the Widget class if that
is the only place it works.
I can deal with this behavior change and I already avoid huge complex
UI designs when I can but I'm kind of annoyed that I'll have to
revisit the ~4 days of spare time that I spent trying out event
processing optimizations and then benchmarking them to find an optimal
one again. :-/
Definitely move it down.
> > I can deal with this behavior change and I already avoid huge complex
> > UI designs when I can but I'm kind of annoyed that I'll have to
> > revisit the ~4 days of spare time that I spent trying out event
> > processing optimizations and then benchmarking them to find an optimal
> > one again. :-/
>
> If you made the change that I suggested (call sinkEvents on the <td>
> UIObject with the Table widget as the listener), would you not get the
> desired behavior?
Maybe/probably, I haven't looked into it. I'm just going to revert to
a basic implementation to get it working for now and will revisit
performance tuning if/when it becomes an issue and/or I have spare
time again.
I know it's been a long time since we visited this issue, but I'm
going to open it up for discussion once again :)
The original event dispatch code in DOMImpl behaved the following way:
- See if the element has an __listener.
- If so, dispatch the event to it.
- If not, go to its parent.
- Wash, rinse, repeat.
I'd love to say that this was part of some grand scheme, but it was
actually an accidental holdover from an old version of the UI library.
It just turned out that it didn't make much of a difference in
practice, as most elements that had events sunk had a __listener, and
it ends up doing much the same thing as event bubbling, except on
those events that don't bubble.
As we were working on 1.4, I was convinced that no one was taking
advantage of this behavior in any useful way. In fact, after we pulled
it out, we found a couple of bugs in existing widgets that were being
masked by it. So we yanked it, fixed the bugs, and moved on happily.
Now Sandy has pointed out a pretty useful side-effect of this
behavior: You can call sinkEvents() on a sub-element of a Widget, and
receive those events on the Widget without having to explicitly sink
events at the top. My first reaction was to suggest simply sinking
those events on the Widget itself, and letting them bubble up. This
has two problems, though:
- Not all events bubble.
- Sinking an event like mousemove at the top causes the Widget to
receive a *lot* of events that it might not be interested in.
The old behavior allowed you to receive events only from a subset of
elements, which can be quite an optimization. But it can also lead to
some slightly weird behavior. Consider the following case:
public SomeWidget() {
setElement(DOM.createDiv());
Element child = DOM.createDiv());
DOM.appendChild(getElement(), child);
sinkEvents(Event.CLICKEVENT);
DOM.sinkEvents(child, Event.CLICKEVENT);
}
Now onBrowserEvent will be fired *twice* for each click on 'child'.
The first time when child gets the event and the dispatcher crawls up
a notch to the root element. The second time when it bubbles up
naturally to the root element. One could argue that this is perfectly
reasonable, given that we called sinkEvents() twice, but I want to
make sure it makes sense to everyone before we consider changing back.
What does everyone think?
joel.
> I couldn't figure out how to cancel the "current" event
> in a generic fashion--it seems you need to be in the
> onBrowserEvent method to do that--so users of
> KeyFilter on any widget besides TextBox will have to
> implement cancelKey themselves.
Perhaps the use case exemplified in that message is rare, but it was
disappointing to find out that a general KeyboardListener can't do
anything useful with the current Event object because it's not
accessible. If you want to preventDefault() or cancelBubble() you
have to be in onBrowserEvent, which can be a lot of work for little
gain. Unfortunately, I'm not sure how to allow greater access to the
current event and still guarantee no memory leaks.
Ian
--
Tired of pop-ups, security holes, and spyware?
Try Firefox: http://www.getfirefox.com
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Google Web Toolkit Contributors" group.
To post to this group, send email to Google-Web-Toolkit-Contributors...@googlegroups.com
To unsubscribe from this group, send email to Google-Web-Toolkit-Contributor s-unsu...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/Google-Web-Toolkit-Contributors?hl=en
-~----------~----~----~----~-- ----~----~------~--~---
With a response like that, I gladly entered an issue. Unfortunately,
there doesn't seem to be a way for me to CC you, so here's the issue
for you to do it yourself:
http://code.google.com/p/google-web-toolkit/issues/detail?id=1309