Project 7: A web browser

The goal of this project is to put together several things you have learned this semester to make an integrated application; most importantly, you will apply multi-threaded programming to a GUI application.

1. Introduction, set up, and overview

In this project, you will write a web-browser. It won't be full-featured, but it will have one interesting feature: It will display text in two panes (like a book), controlled by a single scroll bar. Your result will look like the following:

Only the text of the page will appear, with no attempt to render any markup except for paragraph boundaries. Hyperlinks in the page will not appear as clickable text but instead will be listed in a dropdown menu which the user can select from. When a page is loaded, the drop-down box on upper right part of the window will contain a list of all the parts of the text that are hyperlinked. When the user selects one from the drop-down box, then the page that it links to is loaded into the browser, in place of the current page.

Make a new directory for this project and copy the starter code from the course directory.

cp /Public/cs245/proj7/* .

There are several big steps in this project, and you should work on these one at a time and confirm they work before you go on.

2. The given code

You are given two files, Browser.java and PageModel.java. The former contains all the code for the GUI, plus the main method (it serves as both the "view" and the "controller"). The latter models the information of the currently loaded page. Take a look at these files.

The visible window components are already set up for you in Browser. The work you will have to do in that class is to write listeners for the button, dropdown menu, and scroll bar. The scroll bar requires a different kind of listener---not an ActionListener but an AdjustmentListener.

The PageModel class already has references to certain parts of the GUI, but you will need to add instance variables about the information needed to be stored and modeled. I have also given stubs for methods that I suggest you write for PageModel, but technically that is up to you: Somehow the listeners are going to have to communicate with the model, and you are free to define a different set of method signatures than what I suggest.

Two of the method stubs are in fact private; I put them there to suggest helper methods---that is, to suggest how you might organize the steps in your code.

3. Steps and hints

This will walk you through the required steps.

A. Grabbing the links and the linked text

Let's take a look at how a hyperlink looks in a sample webpage.

<p><b>Bears</b> are <a href="/wiki/Mammal" title="Mammal">mammals</a> of the

We're interested in two things: the href (/wiki/Mammal) and the text that is linked (mammals). We're going to ignore the title. (Arguably the title rather than the linked text is what we should extract, but I would contend that the user is more likely to notice the exact text as it appears on the page.)

So your first task is to modify your code that strips out the tags so that it handles anchor/href tags differently. Ultimately we will need to record the links and the texts, but first, test that you can extract them correctly by printing the links and texts to the screen while your program is processing the web page.

You may find that once you have the basic link-extraction working that you get some extra links that we would rather ignore---for example, links to anchor points within the current page. I suggest including an ad hoc test to weed out those links.

B. Storing the links

Once you are able to extract the links and linked texts, find some way to store them so that they can be used later---specifically, renderPage() will use them to modify the JComboBox. My implementation uses two ArrayLists; alternately a HashMap could be used. Implement this, and test that it works by moving the screen-dump of the texts and links to renderPage() instead of the method where you strip out tags.

C. Working with JComboBoxes

Study the API entry for JComboBox and my use of it in the WikipediaSearch example. In brief, it contains a set of Objects (Strings, for our purposes) that it displays in the drop down menu, and it maintains a "currently selected item"---not only can the user select an item, but it is also possible to set a certain item to be "selected" with code. There are two things we want to do with the JComboBox:

Notice that most of the first point can be achieved using the methods addItem() and removeItemAt() or removeItem(). (There also is a method removeAll(), but I couldn't get that to work correctly... I suspect there is a bug in the version of the library we're using.)

The second point will involve putting an ActionListener on the JComboBox which will react when the user selects something. You can then find out what was selected using getSelectedItem() on the JComboBox.

One thing to be careful about: Whenever you modify the JComboBox in code---such as when removing or adding an item---you will trigger an actionPerformed() on the ActionListener. You need to find a way to distinguish between a user-initiated action and one done in code. I suggest a having an initial blank item in the menu, setting the "selected item" to null while changing the menu, or some combination of those.

Test to see that the right item is selected by printing the selection to the terminal---say, in the method clickLink(). Do this before trying to render the right page (which is going to take more work...)

D. Dealing with relative URIs

Now the final, hard part. If the hyperlinks in the webpage were fully-formed absolute URLs (such as http://en.wikipedia.org/wiki/Mammal), then loading the next page wouldn't be so bad. However, most webpages contain relative links (/wiki/Mammal).

To load the correct page, you need to resolve the relative link to an absolute link. And here's the hint I'll give: look at the method resolve() in class URI.

Then, load a new page, and make sure everything still works---for example, the links in the drop-down menu get reset. And then, you've written a working web browser!

4. Turn in

Copy all the files you made or modified to a turn-in directory I've made for you.

cp filename /cslab.all/ubuntu/cs245/turnin/proj7/{brett,elizabeth,greg,jason,michael}

DUE: Friday, Apr 29, at 5:00


Thomas VanDrunen
Last modified: Tue Apr 19 14:55:10 CDT 2011