The Home Page

The Home page's job is to collect the difficulty and initiate a game:

Figure 7.6. Home.java

public class Home
extends BasePage
implements IActionListener
{
  public static final int EASY = 10;
  public static final int MEDIUM = 5;
  public static final int HARD = 3;

  private int misses;
  private String error;

  public void detach()
  {
    misses = 0;
    error = null;
      
    super.detach();
  }

  public int getMisses()
  {
    return misses;
  }

  public void setMisses(int value)
  {
    misses = value;

    fireObservedChange("misses", value);
  }

  public String getError()
  {
    return error;
  }

  public IActionListener getFormListener()
  {
    return this;
  }

  public void actionTriggered(IComponent component, IRequestCycle cycle)
  throws RequestCycleException
  {
    if (misses == 0)
    {
      error = "Please select a game difficulty.";
      return;
    }

    Visit visit = (Visit)getVisit();

    visit.start(misses);

    cycle.setPage("Guess");
  }

}

We're seeing all the familiar ideas: The misses property is a persistent page property (which means the page will "remember" the value previously selected by the user).

We use a common trick for simple pages: the page contains a single Form component, so we use the page itself as the form's listener, and have the page implement the IActionListener interface.

This saves a bit of code for creating an inner class as the form listener.

Initially, we don't select a difficulty level, and the user can click "Play!" without selecting a value from the list, so we check that.

Otherwise, we get the visit object and ask it to start a new game with the selected number of misses. We then jump to the Guess page to start accepting guesses from the user.

The interesting part of the Home page HTML template is the form:

Figure 7.7. Home.html (excerpt)

<jwc id="form">

<jwc id="group">

<jwc id="ifError">
<font size=+2 color=red><jwc id="insertError"/></font>
</jwc>

<table>
  <tr>
    <td><jwc id="inputEasy"/></td>
    <td>Easy game; you are allowed ten misses.</td>
  </tr>

  <tr>
    <td><jwc id="inputMedium"/></td>
    <td>Medium game; you are allowed five misses.</td>
  </tr>

  <tr>
    <td><jwc id="inputHard"/></td>
    <td>Hard game; you are only allowed three misses.</td>
  </tr>

  <tr>
    <td></td>
    <td><input type="submit" value="Play!"></td>
  </tr>

</table>

</jwc>
</jwc>

Here, the interesting components are group, inputEasy, inputMedium and inputHard. group is type RadioGroup, a wrapper that must go around the Radio components (the other three). The RadioGroup determines what property of the page is to be read and updated (its bound to the misses property). Each Radio button is associated with a particular value to be assigned to the property, when that radio button is selected by the user.

This comes together in the Home page specification:

Figure 7.8. Home.jwc (excerpt)

  <component id="group" type="RadioGroup">
    <binding name="selected" property-path="misses"/>
  </component>
  
  <component id="inputEasy" type="Radio">
    <field-binding name="value" field-name="tutorial.hangman.Home.EASY"/> 1
  </component>
  
  <component id="inputMedium" type="Radio">
    <field-binding name="value" field-name="tutorial.hangman.Home.MEDIUM"/>
  </component>
  
  <component id="inputHard" type="Radio">
    <field-binding name="value" field-name="tutorial.hangman.Home.HARD"/>
  </component>

1

A <field-binding> is like a <static-binding>, except that the static value is taken from a public static field of some class. This makes it easy to coordinate behaviors between the specification and the class.

This is a good thing, since if you decide to make a HARD game only allow two mistakes, you can make the change in exactly one place .. your Java code.

So the end result is: when the user clicks the radio button for a Hard game, the static constant HARD is assigned to the page's misses property.