Posts Tagged 'mvp'

Displaying Links in GWT FlexTables

Lately I’ve been working on displaying links inside of tables in GWT applications. The situation is this. You have a table of information you want  to display. Each row corresponds to a row in a database table. You want to display the table and allow users to select the different rows. You want the display of links controlled by css.

In the past, I’ve simply generated the html for a table and arranged for the right cells to be links to other parts of the application. With GWT, I’ve found at least three ways I could do this with a FlexTable. With this post, I am trying to explain them and think about which way is the best.

The biggest problem is not getting the data displayed. FlexTable makes that very easy. The challenge is figuring out what to do for the css in the table. I want the following:

  • Java code sets the style names for elements, but does not set individual attributes.
    That means that once the code is right, the display can be changed simply by editing the css.
  • The user gets visual feedback as they move the mouse around over the links.
  • The text parts that are links are styled so the user can see that they are links.
    Visited links are displayed in a different color than unvisited links.

It’s turning out to be a bit more complicated than I expected. There are several different methods that you can use and so far, for me at least, there is no perfect solution that works in the browsers I have tried.

Different Methods

  1. Build your own links by using Hyperlink objects.
  2. Rely on CSS pseudo classes for hover (e.g. name-link:hover).
  3. Rely on  Java code to handle mouse-over and mouse-out events. Those handlers could add and remove dependent styles.

1. Building your own links is not too bad an option. If your css works with your target browsers, you get just about everything: roll-over effects for mouse movements, links, and history reflected in visited links. It’s also easy. The code looks something like this:

   Hyperlink nameLink = new Hyperlink ();
   nameLink.setHTML (nameText);
   nameLink.setTargetHistoryToken ("edit="+new Integer (rowSpecificId));
   flexTable.setWidget (rowNum, 1, nameLink);

One negative is that it might not fit in with your notions of events and event handling in GWT. If you want to generate an event when the link is clicked, you don’t have it. Lack of events may also mean you’ve taken a step away from whatever MVP framework you have adopted.

2. The CSS pseudo class approach, where you add “:hover” css classes, is pretty good. For not much effort, you get the roll-over effects you want — though it looks like there could be a few browsers that do not support them completely. You don’t get history, however, so all the areas that you have hover styles display as linked areas, but since they are not links, they look like links without history.

For example, if you have a name-link style and you attach that to the cell that contains the text you want to show as a link, you’d have definitions like the following:

  name-Link {color: #8800AA; text-decoration : underline; cursor:pointer; }
  name-Link:hover {color: #8800AA;  text-decoration : none; background: #eeeeff; cursor: pointer;}
In your Java code, you would have something like:
 flexTable.setText(rowNum, 1, nameText);
 flexTable.getCellFormatter ().addStyleName (rowNum, 1, "name-Link");

3. If you rely on Java code to adjust styles as the mouse moves over linked text, which is what the tips from StudyBlue suggest, you get roll-over effects, but still no history.  Since you are adding click handlers, it makes a certain amount of sense to do the mouse roll-over handlers at the same time.

You won’t be able to use the technique they describe as is because the mouse listener classes have been deprecated. The new handler methods can do the same thing. You end up doing the following for them:

public class MyMouseEventHandler implements MouseOverHandler, MouseOutHandler {
{
  public void onMouseOver(final MouseOverEvent moe) {
    Widget widget = (Widget) moe.getSource();
    widget.addStyleDependentName("hover");
  }
  public void onMouseOut(final MouseOutEvent moe) {
    Widget widget = (Widget) moe.getSource();
    widget.removeStyleDependentName("hover");
  }
}

The Java code you’d use in your view looks like:

You’d also have to have this code in your view.

  Label nameLabel = new Label (nameText);
  nameLabel.setStyleName ("name-Link");
  MyMouseEventHandler meh = new MyMouseEventHandler ();
  nameLabel.addMouseOverHandler (meh);
  nameLabel.addMouseOutHandler (meh);
  flexTable.setWidget (rowNum, 1, nameLabel);

For styles, you’d have class names “name-Link” and “name-Link-hover” since adding a dependent style name of “hover” results in “-hover” being added to the name.

Conclusion

The way I see it, the Hyperlink method has a lot going for it. It makes the most of standard css and counts on the browsers to do their job in handling history and supporting css. What concerns me is that seems to be leading me away from the MVP framework that I wanted to try out. (For more on this, see my earlier note on MVP).

Because of that, I am going to to stay away from generating Hyperlinks and go with an approach that relies on Java code setting up click events for the rows in the table. I don’t yet see the value in handling mouse roll-over like what was suggested by the StudyBlue people. You have sufficient control using the CSS pseudo classes (e.g. “:hover”), and doing it that way does not require additional Java code.

This analysis is based on my work with GWT 2.0 and the following browsers: IE 8, Firefox 3.6.6, Chrome 5.0.375, and Safari 4.0.5.

Of course, GWT is still pretty new to me, and I may have missed something. I welcome the comments and suggestions of others.

Going with Google Code

In my last post, I talked about two different frameworks for MVP that I was studying. Which one should I use for my work?

Well, I really want to use the GWT-Presenter framework. I just have not been able to get it going. You can get the code for it via SVN — version 1 or newer — but I kept finding all sorts of new features and improvements while reading other people’s blog’s (David Chapman’s blog, in particular). Without examples of use of the new features, I was not making the progress I wanted to make on the app side.

So, for now, I am going with the framework illustrated by the Google folks. That’s Large Scale Application Development and MVP.

How to do MVP

I have found a couple of great examples of using the Model-View-Presenter pattern with GWT (Google Web Toolkit).

  1. Large Scale Application Development and MVP – posted in the Google code website. It has a good example of a Contact application. This seems like a very straightforward approach
  2. GWT-Presenter- This framework looks to be very well designed. Their example is a replacement for the greeting test app you get when you create a new GWT application in Eclipse. For more on this framework, see Chris Lowe’s blog.

The big questions for me follow.

  • What are the differences in the two frameworks?
  • Which framework should be the starting point for my work?

What are the differences in the two frameworks?

My sense right now is that there is something very compelling about Framework 1 (from Google Code). It seems so straightforward and takes care of the essential elements: (1) MVP;  (2) events and event bus; (3) getting browser history right so you can bookmark pages; (4) easily tested.  Their discussion of events is good and they make a point that you really only want to have app-wide events on the event bus. They warn against getting “bogged down in event handling”. For the Contact app example, they list 5 events and 5 event handlers that they have defined. It feels about right to me, meaning the events make sense as things you’d have to know about in order to present the user with the right view at the right time.

One thing to note about the example of Framework 1. It does have a server side for updating contacts, but is totally mocked up. It’s not really stored in a database and you can only have one new contact at a time. Each time add a new contact, it updates the list item on the list it is maintaining on the server side.

Framework 1 handles history by having its AppController track ValueChangeEvents from the History object. So AppController implements onValueChange, and it’s there that it checks the history token and locates the next Presenter to run. It looks a bit like:

public class AppController implements ValueChangeHandler { 
  ... 
  public void onValueChange(ValueChangeEvent event) { 
    String token = event.getValue(); 

    if (token != null) { 
      Presenter presenter = null; 

      if (token.equals("list")) { 
        presenter = new ContactsPresenter(rpcService, eventBus, new ContactView()); 
      } 
      else if (token.equals("add")) { 
        presenter = new EditContactPresenter(rpcService, eventBus, new EditContactView()); 
      } 
      else if (token.equals("edit")) { 
        presenter = new EditContactPresenter(rpcService, eventBus, new EditContactView()); 
      } 

      if (presenter != null) { 
        presenter.go(container); 
      }
    } 
}

What I like about Framework 2 (GWT-Presenter) is that it has all the things that Ray Ryan talked about. It makes use of Dependency Injection using Guice and GIN, and it looks like it has a little bit more developed handling of history, as embodied in a PlaceRequest object.

What framework should be the starting point of my work?

I don’t know yet. My next step will be to take the Google Code Contact example and redo it on top of GWT-Presenter. That will test my understanding of GWT-Presenter. I expect to find that GWT-Presenter is just a little bit better in its handling of events and places. Besides, it will force me to come to terms with DependencyInjection (DI), which Ray Ryan insists is not such a big deal and is really good for you.

GWT Best Practices

Like many people, I have been inspired by the talk given by Ray Ryan on “Best Practices for Architecting Your GWT App”.

If you prefer reading to listening, check out the slides and transcripts of the talk.



Follow

Get every new post delivered to your Inbox.

Join 72 other followers