Lebowski
Lebowski

Reputation: 145

Creating a Web Browser in Java

I was wondering if someone could help me figure out what is wrong with my code. I am trying to create a web browsers back and forward buttons. I use Javas "Deque" (which is like a stack with more functionality) to keep track of current and previous visited pages. Problem is that after much debugging I don't know what is wrong. The ordered is not kept for some reason and I can't figure out why. Any help is appreciated. The code only works for the hyperlinks so far but if I can get that to work is easy to get the other part to work when the user inputs manually a URL. Thanks :)

import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Deque;

/**
 * This class includes Jbuttons, JTextFields, ScrollPane and View
 * Created by Nash on 12/16/2015.
 */
public class Controller extends JPanel implements ActionListener, HyperlinkListener {

    private JButton button;
    private JButton back;
    private JButton front;
    private JTextField addressBar;
    private JScrollPane scrollBar;
    private View view;
    private int padding = 5;
    private String current = "https://www.kth.se";
    private Deque<String> historyBack = new ArrayDeque<>();
    private Deque<String> historyFront = new ArrayDeque<>();


    /**
     * Constructor name: Controller
     * Includes:    all the buttons
     *              actionPerformed method
     *              hyperlinkUpdate method
     * @param v
     */
    public Controller(View v){

        this.view = v;

        this.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();

        /* Back button */
        back = new JButton("<");
        back.setName("back");
        back.setEnabled(false);
        back.addActionListener(this);
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.0;
        c.weighty = 0.0;
        c.gridx = 0;
        c.gridy = 0;
        c.ipady = padding;
        this.add(back, c);

        /* Front button */
        front = new JButton(">");
        front.setName("front");
        front.setEnabled(false);
        front.addActionListener(this);
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.0;
        c.weighty = 0.0;
        c.gridx = 1;
        c.gridy = 0;
        c.ipady = padding;
        this.add(front, c);

        /* URL address bar */
        addressBar = new JTextField();
        addressBar.addActionListener(this);
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 1.0;
        c.weighty = 0.0;
        c.gridx = 2;
        c.gridy = 0;
        this.add(addressBar, c);

         /* Go button */
        button = new JButton("Go!");
        button.addActionListener(this);
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.0;
        c.weighty = 0.0;
        c.gridx = 3;
        c.gridy = 0;
        c.ipady = padding;
        this.add(button, c);

        this.view.addHyperlinkListener(this);

        scrollBar = new JScrollPane(v);
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 1.0;
        c.weighty = 1;
        c.gridx = 0;
        c.gridy = 1;
        c.gridwidth = 4;
        c.insets = new Insets(10,0,10,0);
        this.add(scrollBar, c);

        try{
            view.setPage(current);
            addressBar.setText(current);
        }catch(IOException e){
            System.out.println("Error: " + e.toString());
        }

    }

    /**
     * Method name:     actionPerformed
     * This method sets the page from the user given URL address
     * @param e
     */

    public void actionPerformed(ActionEvent e){
        if(e.getSource() == back){
            if(!historyBack.isEmpty()) {
                goBack();
            }else{
                back.setEnabled(false);
            }
        } else if(e.getSource() == front){
            if(!historyFront.isEmpty()) {
                goFront();
            }else{
                front.setEnabled(false);
            }
        } else {
            try {
                // I can fix this later after the hyperlinks work! Skip this
                current = addressBar.getText();
                System.out.println("n: " + current);          // Print URL
                view.setPage(current);
                addressBar.setText(current);
                historyBack.addFirst(view.getPage().toString());

            }catch(IOException arg0){
                view.setText("404 error... PAGE NOT FOUND!");

                System.out.println("error " + arg0.toString());
            }
        }
    }


    /**
     * Method name:     hyperlinkUpdate
     * This method sets the page to the clicked hyperlink address
     * @param e
     */
    public void hyperlinkUpdate(HyperlinkEvent e){
        if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED){
            try {
                current = e.getURL().toExternalForm();
                view.setPage(current);
                addressBar.setText(current);
                System.out.println("back saved & front cleared: " + view.getPage().toString());
                historyBack.addFirst(view.getPage().toString());
                historyFront.clear();
                if(!historyBack.isEmpty()) {
                    back.setEnabled(true);
                }else{
                    back.setEnabled(false);
                }
                if(!historyFront.isEmpty()) {
                    front.setEnabled(true);
                }else{
                    front.setEnabled(false);
                }
            }catch(IOException arg0){
                System.out.println("error " + arg0.toString());
            }
        }
    }

    public void goBack(){
        try{
            if(!historyBack.isEmpty()) {
                String removed = historyBack.removeFirst();
                view.setPage(removed);
                addressBar.setText(removed);
                historyFront.add(view.getPage().toString());
                System.out.println("front saved: " + view.getPage().toString());
                if(!historyBack.isEmpty()) {
                    back.setEnabled(true);
                }else{
                    back.setEnabled(false);
                }
                if(!historyFront.isEmpty()) {
                    front.setEnabled(true);
                }else{
                    front.setEnabled(false);
                }
            }
        } catch(IOException arg0){
            System.out.println("Error: " + arg0.toString());
        }
    }

    public void goFront(){
        try{
            if(!historyFront.isEmpty()) {
                String removed = historyFront.removeFirst();
                view.setPage(removed);
                addressBar.setText(removed);
                historyBack.add(view.getPage().toString());
                System.out.println("back saved: " + view.getPage().toString());
                if(!historyFront.isEmpty()) {
                    front.setEnabled(true);
                }else{
                    front.setEnabled(false);
                }
                if(!historyBack.isEmpty()) {
                    back.setEnabled(true);
                }else{
                    back.setEnabled(false);
                }

            }
        } catch(IOException arg0){
            System.out.println("Error: " + arg0.toString());
        }
    }

}

Upvotes: 0

Views: 116

Answers (1)

Andreas
Andreas

Reputation: 159086

Both historyBack and historyFront should work like a stack, something like this:

  • When clicking a link, you push current page on the "back" stack, clear the "front" stack, and show the new page.

  • When clicking the back button, you push current page on the "front" stack, pop to top value from the "back" stack, and show that page.

  • When clicking the forward button, you push current page on the "back" stack, pop to top value from the "front" stack, and show that page.

As you can see, it's pure stack operations.

Deque has stack methods push() and pop(), implemented to be same as addFirst() and removeFirst(). You could call those directly, but using push() and pop() helps clarify the stack functionality.

Alternatively, you can call addLast() and removeLast(), with add() being synonymous with addLast().

What you cannot do, if you want stack functionality, is to mix them, and you are.

Searching your code for use of historyBack shows:

historyBack.isEmpty()
historyBack.addFirst()
historyBack.removeFirst()
historyBack.add()          <==== WRONG

Searching your code for use of historyFront shows:

historyFront.isEmpty()
historyFront.clear()
historyFront.add()         <==== WRONG
historyFront.removeFirst()

You are mixing them!!! Change to use push() and pop(), and you cannot accidentally mix them.

Upvotes: 1

Related Questions