public ConversationView(ClientModel cm, String thisUser, String thatUser) {
        super("Conversation");

        // Creates a frame reference
        this.frame = this;

        // Sets up Menu
        setUpMenu();

        // To schedule updates to conversational status
        scheduler = Executors.newScheduledThreadPool(20);

        // Instantiating 
        clientModel = cm;
        thisUsername = thisUser;
        thatUsername = thatUser;
        myTypingStatus = "NOT TYPING";
        theirTypingStatus = "NOT TYPING";
        lastTypeTime = 0;

        // Construct components
        cp = new JPanel();
        GridBagLayout gbpanel = new GridBagLayout();
        GridBagConstraints gbcpanel = new GridBagConstraints();
        cp.setLayout(gbpanel);
        
        // Make the text area
        convoText = new JTextArea(18, 30);

        // Set locations of the components
        gbcpanel.gridx = 0;
        gbcpanel.gridy = 0;
        gbcpanel.gridwidth = 20;
        gbcpanel.gridheight = 16;
        gbcpanel.fill = GridBagConstraints.BOTH;
        gbcpanel.weightx = 1;
        gbcpanel.weighty = 1;
        gbcpanel.anchor = GridBagConstraints.NORTH;

        // Make a scroller for the convo
        JScrollPane scroller = new JScrollPane(convoText);

        // Set constraints
        gbpanel.setConstraints(scroller, gbcpanel);

        // Add the scroller to the contentPane and set convoText defaults
        cp.add(scroller);
        convoText.setEditable(false);
        convoText.setLineWrap(true);
        convoText.setWrapStyleWord(true);

        // Make the input area
        msgField = new JTextField();
        
        // Attach it to the grid
        gbcpanel.gridx = 1;
        gbcpanel.gridy = 17;
        gbcpanel.gridwidth = 15;// GridBagConstraints.RELATIVE;
        gbcpanel.gridheight = 2;
        gbcpanel.fill = GridBagConstraints.BOTH;
        gbcpanel.weightx = 1;
        gbcpanel.weighty = 0;
        gbcpanel.anchor = GridBagConstraints.NORTH;
        gbpanel.setConstraints(msgField, gbcpanel);
        cp.add(msgField);

        // for determining whether to send typing
        msgField.addKeyListener(new KeyListener() {

            @Override
            public void keyPressed(KeyEvent arg0) {}

            @Override
            public void keyReleased(KeyEvent arg0) {}

            @Override
            public void keyTyped(KeyEvent arg0) {
                // Set lastTyping time
                lastTypeTime = System.currentTimeMillis();
                if (!myTypingStatus.equals("TYPING")) {
                    myTypingStatus = "TYPING";
                    try {
                        clientModel.setTypingStatus(thatUsername,
                                myTypingStatus);
                    } catch (IOException e) {
                        // server failed!
                    }
                }
            }

        });

        // Send button
        sendBtn = new JButton("Send");
        // Location
        gbcpanel.gridx = GridBagConstraints.RELATIVE;
        gbcpanel.gridy = 17;
        gbcpanel.gridwidth = 4;
        gbcpanel.gridheight = 2;
        gbcpanel.fill = GridBagConstraints.NONE;
        gbcpanel.weightx = 1;
        gbcpanel.weighty = 0;
        gbcpanel.anchor = GridBagConstraints.EAST;
        gbpanel.setConstraints(sendBtn, gbcpanel);
        cp.add(sendBtn);

        // Send the message
        sendBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    // Don't send a message if the field is empty
                    if (msgField.getText().trim().equals("")) {
                        return;
                    }

                    clientModel.sendPM(thatUsername, msgField.getText());
                    msgField.setText("");
                    lastTypeTime = System.currentTimeMillis();
                    if (!myTypingStatus.equals("NOT TYPING")) {
                        myTypingStatus = "NOT TYPING";
                        clientModel.setTypingStatus(thatUsername,
                                myTypingStatus);
                    }
                } catch (IOException e1) {
                    // Server DIED
                }
            }
        });

        // Sets the window typing status
        updateWinTitle();

        // Close the window on exit
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        // Set size
        setPreferredSize(new Dimension(500, 310));// setResizable(false);

        // Clean up
        setContentPane(cp);
        pack();
        setVisible(true);

        // Update the typing status consistently
        scheduler.scheduleAtFixedRate(new UpdateMyTypingStatus(), 0, 3,
                TimeUnit.SECONDS);
    }