Thomas,

I need to think more about this approach. Ray mentioned in his talk
about having too many events and performance. Does your approach not
lead to that?

-mic

On Apr 1, 3:16 am, Thomas Broyer <[email protected]> wrote:
> On Apr 1, 1:15 am, Nathan Wells <[email protected]> wrote:
>
> > Thomas,
>
> > I've heard of your approach before, but I'm not clear on the
> > implementation... are you passing the presenter itself into the view?
> > or are you passing instances of event handlers? The difference seems
> > trivial, but in practice (as I imagine it, anyway) seems large:
>
> >http://etherpad.com/sIAaiCfuiG
>
> > Let me know what you think. I would assume the first way is what your
> > referring to in your comment above, which implies that it is a View
> > layer responsibility to deal with HandlerRegistrations and the like.
> > Is that correct?
>
> Yes. It makes a few things much easier for me:
>  - I can use @UiHandler in the view, which makes the whole thing more
> readable (on the down-side, I used to create a class that implement
> all required handlers instead of using an anonymous class per handler;
> UiBinder doesn't do this optimization (yet?) with @UiHandlers)
>  - I can use event delegation in the view
>  - The view methods are more "consistent" (get/setUserName and
> setUserNameEnabled(boolean), vs. getUserName->get/setText and
> setUserNameEnabled(boolean); this elad people to ask for a HasEnable
> interface, which wouldn't solve anything as you'd still need
> getUserName->HasText and getUserNameEnablable->HasEnable), even more
> when also dealing with non-widget UI elements: I implemented a login
> form with a <form> in the HTML page which action="" is set to callback
> a GWT method ($wnd.__form_callback = $entry([email protected]())) and
> had to create a dummy HasClickHandlers to return as the
> "HasClickHandlers submitButton()"; with a Listener is way easier: the
> onSubmit just calls back the listener.submit().
>  - I have one "screen" where the user can add files to upload, each
> "file" is a line composed of a FileUpload and a "cancel" button next
> to it that removes the "line" from the screen (and therefore "cancels
> the file" before the form is submitted), already uploaded files
> (unpredictable number) are shown as a label with a "delete" button
> next to it. Add to this that files are grouped into dynamic,
> unpredictable "groups". Previously, I did everything with a
> SelectionEvent<String> where the value was something like "add:<file
> group>", "cancel:<file id>", or "delete:<file id>" (I use event
> delegation in the view). Now, instead of firing a SelectionEvent with
> a specific value, I just call the listener's addFile(String group),
> cancelFile(String fileId) or deleteFile(String fileId).
> Sure I could have defined new events instead of doing it all through a
> SelectionEvent but it wouldn't have make things much easier, with more
> files to maintain.
>
> As for the implementation, I currently have something like:
> public class FooPresenter {
>   @ImplementedBy(FooView.class)
>   public interface Display {
>     void setListener(Listener listener);
>
>     void setThisVisible(boolean visible);
>
>     void setThatEnabled(boolean enabled);
>   }
>
>   public interface Listener {
>     void save();
>
>     void close();
>   }
>
>   private class Handlers implements PlaceHandler,
> SomeOtherBusEventHandler, Listener {
>     ...
>   }
>
>   @Inject
>   public FooPresenter(Display view, EventBus bus) {
>     Handlers handlers = new Handlers();
>     bus.addHandler(PlaceEvent.getType(), handlers);
>     bus.addHandler(SomeOtherBusEvent.getType(), handlers);
>     view.setListener(handlers);
>   }
>
>   ...
>
> }
>
> public class FooView implements FooPresenter.Display {
>   @UiField Button save;
>   @UiField Button close;
>
>   private FooPresenter.Listener listener;
>
>   ...
>
>   public void setListener(FooPresenter.Listener listener) {
>     assert listener != null;
>     this.listener = listener;
>   }
>
>   @UiHandler("close")
>   void onCloseClick(ClickEvent event) {
>     listener.close();
>   }
>
>   @UiHandler("save")
>   void onSaveClick(ClickEvent event) {
>     listener.save();
>   }
>
> }
>
> I'm using a Listener *interface* so the view doesn't have direct
> dependencies on the presenter's behavior (I could therefore mock a
> Listener and make a small app to "manually test" my view without
> actually having any presenter, event bus, etc.)
>
> I decided to switch to this design instead of HasXxxHandlers when I
> saw Ray's work on RequestFactory: """In the Wave style: the view
> (editor) has a single listener for its semantic operations."""
> The main difference is that I do not have an interface for each
> presenter with its impl class (interface FooPresenter / class
> FooPresenterImpl implements FooPresenter, FooPresenter.Listener) so my
> presenter class doesn't itself implement the listener interface (it
> would also "pollute" its public API, which is not a problem in Ray's
> case where no other object has a direct dependency on the Impl class,
> only on the presenter interface).
> In a new project we're starting, I might reconsider this approach
> though, and introduce an interface vs. impl class dichotomy all over
> the place.
>
> Something to be aware of though: the Listener approach puts a bit more
> responsibility into the view than the HasXxxHandlers approach, but
> it's so much easier to work with (and write unit tests) that's I think
> it's worth it.

-- 
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.

Reply via email to