Responses below. No code changes yet.

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/gwt/user/client/ui/DefaultEventBusProvider.java
File user/src/com/google/gwt/user/client/ui/DefaultEventBusProvider.java
(right):

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/gwt/user/client/ui/DefaultEventBusProvider.java#newcode41
user/src/com/google/gwt/user/client/ui/DefaultEventBusProvider.java:41:
public static DefaultEventBusProvider instance() {
Yes, but I need to add the javax.inject package to GWT. I'll put a TODO.

Re: setInstance(), I've generally seen such things cause more harm than
good, especially in test code.

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/gwt/user/client/ui/DefaultEventBusProvider.java#newcode54
user/src/com/google/gwt/user/client/ui/DefaultEventBusProvider.java:54:
public static DefaultEventBusProvider instanceMaybe() {
You don't write a lot of app unit tests, do you?

The expectation is that instanceMaybe() will be used rarely, and only by
library developers. An app either uses the default bus (and so would
call instance), or it doesn't, and so would never refer to this class.
And even then, most app code would receive an eventBus as a constructor
argument, or would ask a Widget for it. If your app is littered with
references to this class, you screwed up. Perhaps the javadoc should say
so.

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/gwt/user/client/ui/DefaultEventBusProvider.java#newcode68
user/src/com/google/gwt/user/client/ui/DefaultEventBusProvider.java:68:
public EventBus get() {
I'll look at that, thanks.

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/gwt/user/client/ui/IsEventSource.java
File user/src/com/google/gwt/user/client/ui/IsEventSource.java (right):

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/gwt/user/client/ui/IsEventSource.java#newcode28
user/src/com/google/gwt/user/client/ui/IsEventSource.java:28: * event
bus.
I've  gone back and forth on this. The idea with a string based approach
is that it makes sketching in ui.xml a lot simpler:

<gwt:Button eventSourceName="save">Save</gwt:Button>
<gwt:Button eventSourceName="delete">Delete</gwt:Button>

Elsewhere your app can register handlers for click events with those
names.
And it's not such a big deal to make those strings as unique as you need
them.

Perhaps the thing to do is provide a convenience setter for the string
case?

Object getEventSource()
void setEventSource(Object)
void setEventSourceName(String)

Too confusing?

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/gwt/user/client/ui/IsWidgetDriver.java
File user/src/com/google/gwt/user/client/ui/IsWidgetDriver.java (right):

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/gwt/user/client/ui/IsWidgetDriver.java#newcode53
user/src/com/google/gwt/user/client/ui/IsWidgetDriver.java:53: public
interface IsWidgetDriver {
I'd rather change the name than add another dimension of indirection to
our world. DrivesWidgets? Ditto for the abstract class. I'd rather
gamble that this is the right api than force clients to deal with an
abstract class. And to that end, I don't think I should include this in
2.4

On 2011/06/14 12:29:25, bobv wrote:
This type name implies there should be a single method

   WidgetDriver asWidgetDriver();

WidgetDriver could then be an abstract base class to allow additional
lifecycle
methods to be added in the future.

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/gwt/user/client/ui/Widget.java
File user/src/com/google/gwt/user/client/ui/Widget.java (right):

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/gwt/user/client/ui/Widget.java#newcode252
user/src/com/google/gwt/user/client/ui/Widget.java:252: * particular,
hiding a parent does not stop the drivers of its children.
On 2011/06/14 15:05:48, jlabanca wrote:
This sounds like its going to cause problems.  If I detach a Panel,
ondetach
will bubble down and stop the child drivers.  But if I hide a Panel,
that does
not happen. That inconsistency is confusing and hard to work around.
start()
doesn't have enough information to know if I'm invisible or if I'm
detached, and
I only need to descend in one of those cases.

Instead, we could introduce two new methods to Widget: startDriver()
and
stopDriver().  The contract of both methods should be that they
descend into
child widgets.  By default, we call these methods from
onAttach/onDetach/setVisible.

These would be protected methods, right?

Users should be able to set a boolean so they can manually control the
driver
(possibly as an optional arg to setNextDriver).  If they take manual
control,
then the user is responsible for calling startDriver/stopDriver.  This
is
particularly useful if you plan to attach/detach to widget often and
don't
necessarily want to kill the driver. Its also useful if you don't want
to
disable the driver when the widget is invisible.

I don't understand this. What's the point of setting the driver if you
don't want the widget to call its start and stop methods for you? If I
want to take manual control I can override startDriver() and
stopDriver(), no?

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/gwt/user/client/ui/Widget.java#newcode268
user/src/com/google/gwt/user/client/ui/Widget.java:268: driver.stop();
I'm also concerned that providing only setNextDriver might be too
inflexible. Should there be a setDriver() as well, which takes effect
immediately? My instinct was to start with only this one and see if
people ask for more.

On 2011/06/14 15:05:48, jlabanca wrote:
What if I set the driver within driver.stop()?  For example, maybe I
have a two
drivers: one when the widget is active, one when its inactive, and I
swap them
back and forth.

This should be more resilient:
IsWidgetDriver oldDriver = driver;
IsWidgetDriver newDriver = nextDriver;
driver = nextDriver;
if (...) {oldDriver.stop();}

// If setNextDriver was called in stop, newDriver is unused.
// Need to wait for updateDriver to execute asynchronously.
if (newDriver == nextDriver && ...) {
   nextDriver = null;
   newDriver.start()
}

Nice. Thanks for this.

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/gwt/user/client/ui/Widget.java#newcode320
user/src/com/google/gwt/user/client/ui/Widget.java:320: driver.start();
How about protected boolean isActive() method, with a default
implementation based on attached and visible? This setVisible method
might become:

    if ((driver != null) && isActive()) {
      startDriver();
    }
    super.setVisible(visible);
    if ((driver != null) && !isActive()) {
      stopDriver();
    }

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/gwt/user/client/ui/Widget.java#newcode364
user/src/com/google/gwt/user/client/ui/Widget.java:364: return new
ResettableEventBus(requireEventBus(), getEventSourceName());
Exactly. And calling ResettableEventBus#die turns the fire method into
no-ops, so the driver doesn't need to have a bunch of if(dead) calls in
its async callbacks.

I should bunch of the javadoc to point out that this is particularly
useful  to the widget's driver.

On 2011/06/14 15:05:48, jlabanca wrote:
Is like a temporary event bus?  Is the idea that a driver will spawn
an event
bus and use it until its stopped?

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/gwt/user/client/ui/Widget.java#newcode434
user/src/com/google/gwt/user/client/ui/Widget.java:434:
DefaultEventBusProvider ebProvider =
DefaultEventBusProvider.instanceMaybe();
On 2011/06/14 15:05:48, jlabanca wrote:
This might be a bit too smart.  getEventBus() may or may not return
null
depending on when the user adds a handler to
DefaultEventBusProvider.instance().

DefaultEventBusProvider.instance().eventBus().addHandler(...)
myWidget.getEventBus().addHandler(); // Works


myWidget.getEventBus().addHandler(); // NPE
DefaultEventBusProvider.instance().eventBus().addHandler(...)


This isn't a public method. spawnEventBus is the only public way to get
one, and that will never be null.

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/gwt/user/client/ui/Widget.java#newcode580
user/src/com/google/gwt/user/client/ui/Widget.java:580: protected
EventBus requireEventBus() {
Okay, I guess. But as you read this is it clear to you that
getEventBus() and requireEventBus() are protected calls? The only public
way to get an event bus off of a widget is through spawnEventBus, which
calls here.

And I'm missing some important javadoc on setEventBus(). Calling that
with null will not stop the widget from posting events, it will make it
post to the default event bus (if there is one). To actually silence a
widget you have to call setEventBus with something like a NullEventBus
instance.

The goal here is to make it simple for apps to do the event bus thing
without having to completely convert to a DI approach, but at the same
time allow DI apps to do it the "right" way.

On 2011/06/14 12:29:25, bobv wrote:
Instead of having two getEventBusMethods(), what about placing a
boolean flag on
getEventBus() to say "don't return null" or at least delegating from
getEventBus() to getEventBus(boolean) so there's only one method that
actually
makes EventBus objects pop into existence?

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/gwt/user/client/ui/Widget.java#newcode583
user/src/com/google/gwt/user/client/ui/Widget.java:583: return
specifiedEventBus;
On 2011/06/14 15:05:48, jlabanca wrote:
If I call requireEventBus, the next call to getEventBus() still
returns null.

No it doesn't. It returns the default event bus. By calling
DEBP.instance() we force the DEBP singleton into existence. The next
call to getEventBus() will return that.

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/web/bindery/event/shared/HandlerRegistration.java
File
user/src/com/google/web/bindery/event/shared/HandlerRegistration.java
(right):

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/web/bindery/event/shared/HandlerRegistration.java#newcode37
user/src/com/google/web/bindery/event/shared/HandlerRegistration.java:37:
public class Null implements HandlerRegistration {
Good point, I'll move it.

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/web/bindery/event/shared/ResettableEventBus.java
File
user/src/com/google/web/bindery/event/shared/ResettableEventBus.java
(right):

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/web/bindery/event/shared/ResettableEventBus.java#newcode37
user/src/com/google/web/bindery/event/shared/ResettableEventBus.java:37:
public ResettableEventBus(EventBus wrappedBus, String name) {
You okay with the setEventSource(Object) / setEventSourceName(String)
notion to keep uibinder simple?

On 2011/06/14 12:29:25, bobv wrote:
If the eventSourceName is turned into an Object eventSourceTag, it
would allow
users to use enums or other Objects for dispatch instead of descending
into
String-matching hell.

http://gwt-code-reviews.appspot.com/1449817/diff/4001/user/src/com/google/web/bindery/event/shared/ResettableEventBus.java#newcode55
user/src/com/google/web/bindery/event/shared/ResettableEventBus.java:55:
* Remove all handlers that have been added through this wrapper, and
neuter
Okay.

On 2011/06/14 15:05:48, jlabanca wrote:
We should rename the method to neuter()

http://gwt-code-reviews.appspot.com/1449817/

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to