com.dbschools.quickquiz.client.taker.MainWindow.java Source code

Java tutorial

Introduction

Here is the source code for com.dbschools.quickquiz.client.taker.MainWindow.java

Source

/*
 * QuickQuiz
 * Copyright (C) 20052009 David C. Briccetti
 * www.davebsoft.com
 *
 * This program is free software; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 2 of the License, or 
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software Foundation, 
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

package com.dbschools.quickquiz.client.taker;

import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.WindowEvent;
import java.text.MessageFormat;

import javax.swing.*;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.ParseException;
import org.apache.log4j.Logger;
import org.jgroups.Address;
import org.jgroups.ChannelException;
import org.jgroups.Message;

import com.dbschools.gui.ErrorHandler;
import com.dbschools.gui.LookAndFeelUtil;
import com.dbschools.gui.MacGuiConfig;
import com.dbschools.gui.TitleBlinker;
import com.dbschools.quickquiz.MessagesListModel;
import com.dbschools.quickquiz.Quiz;
import com.dbschools.quickquiz.QuizTaker;
import com.dbschools.quickquiz.client.AbstractClientWindow;
import com.dbschools.quickquiz.client.Resources;
import com.dbschools.quickquiz.client.QuizState;
import com.dbschools.quickquiz.msg.*;
import com.dbschools.quickquiz.netwrk.QuizController;

/**
 * Quiz taker client application.
 * 
 * @author David C. Briccetti
 */
public final class MainWindow extends AbstractClientWindow implements FocusListener, TakerReceivedMessageProcessor {

    private static final long serialVersionUID = -1305289771253713033L;
    private final static Logger log = Logger.getLogger(MainWindow.class);
    private MessagesListModel messagesModel;
    private final String takerName;
    private final Quiz quiz;
    private final QuizController quizController;

    public static void main(final String args[]) throws ParseException, ChannelException {
        MacGuiConfig.config(Resources.getString("macGiverTitle"));
        LookAndFeelUtil.setSystemLookAndFeel();
        final CommandLine line = com.dbschools.quickquiz.client.CommandLine.processCmdLine(args, null);
        TakerLauncher.launchTakerWithSelectedQuiz(line);
    }

    MainWindow(Quiz selectedQuiz, String takerName, QuizController quizController) {
        super(selectedQuiz.getName());
        this.quiz = selectedQuiz;
        this.takerName = takerName;
        this.quizController = quizController;
        initComponents();
        pnlPlayers.add(takerTableDisplay);
    }

    final void initialize() throws ChannelException {
        txtChatLine.addFocusListener(this);
        txtAnswer.addFocusListener(this);

        quizChannel = quizController.joinQuizChannel(quiz);
        quizChannel.setReceiver(new Receiver(this));
        quizChannel.send(null, null, new JoiningMsg(new QuizTaker(this.takerName, quizChannel.getLocalAddress())));
        quizChannel.getState(null, 5000);

        messagesModel = (MessagesListModel) lstMessages.getModel();
    }

    @Override
    public void processReceivedMsg(final Message msg) {
        final Object msgObj = msg.getObject();
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                if (msgObj instanceof ChatMsg) {
                    processIncomingChatMsg((ChatMsg) msgObj);
                } else if (msgObj instanceof QuizOverMsg) {
                    processQuizOverMsg();
                } else if (msgObj instanceof JoiningMsg) {
                    processJoiningMsg(msg.getSrc(), msgObj);
                } else if (msgObj instanceof QuestionMsg) {
                    processQuestionMsg((QuestionMsg) msgObj);
                } else if (msgObj instanceof QuestionOverMsg) {
                    processQuestionOver();
                } else if (msgObj instanceof TakerUpdateMsg) {
                    processUpdatedTaker(((TakerUpdateMsg) msgObj).getTaker());
                } else if (msgObj instanceof PointsAwardedMsg) {
                    processPointsAwardedMsg(((PointsAwardedMsg) msgObj));
                } else if (msgObj instanceof ChatEnableMsg) {
                    processChatEnableMsg(msgObj);
                }
            }
        });
    }

    protected MessagesListModel getMessagesListModel() {
        return messagesModel;
    }

    protected JScrollBar getMessagesScrollBar() {
        return scpMessages.getVerticalScrollBar();
    }

    protected JPanel getChatPanel() {
        return pnlChat;
    }

    protected JPanel getMessagesPanel() {
        return pnlMessages;
    }

    private void processQuestionMsg(QuestionMsg questionMsg) {
        final String question = questionMsg.getQuestion();
        final Integer timeLimit = questionMsg.getTimeLimitSeconds();
        lblQuestion.setText(question);

        messagesModel.add(new MessageFormat(Resources.getString("questionReceived"))
                .format(new Object[] { questionMsg.getCreationTime(), timeLimit, question }));

        /* Configure input controls */
        txtAnswer.requestFocus();
        btnSubmit.setEnabled(true);
        btnSendChatLine.setEnabled(false);

        /* Start countdown meter */
        if (timeLimit != null && timeLimit > 0) {
            countdownMeter.countDown(timeLimit);
        }

        /* Blink the QA panel title */
        new TitleBlinker(pnlQA).blink();
    }

    private void processQuestionOver() {
        lblQuestion.setText(Resources.getString("waitingForNextQuestion"));
        btnSubmit.setEnabled(false);
        restoreChat();
    }

    private void processQuizOverMsg() {
        final MessageFormat formatter = new MessageFormat(Resources.getString("quizOver"));
        JOptionPane.showMessageDialog(MainWindow.this, formatter.format(new Object[] { getQuizName() }));
        deregister();
        System.exit(0);
    }

    private void processChatEnableMsg(Object msgObj) {
        final boolean enabled = ((ChatEnableMsg) msgObj).getChatEnabled();
        configureChatSendButton(enabled);
        getQuizState().setChatEnabled(enabled);
    }

    private void configureChatSendButton(boolean enabled) {
        btnSendChatLine.setEnabled(enabled);
        btnSendChatLine.setText(enabled ? "Send" : "Disabled");
    }

    public void processNewQuizState(QuizState quizState) {
        setQuizState(quizState);
        configureChatSendButton(quizState.isChatEnabled());
        takerTableDisplay.setTakers(quizState.getTakers().values());
    }

    private final void btnSendChatLineActionPerformed(final java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSendChatLineActionPerformed
        handleSendingChatMsg(quizChannel, txtChatLine, takerName);
    }//GEN-LAST:event_btnSendChatLineActionPerformed

    private final void btnSubmitActionPerformed(final java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSubmitActionPerformed
        String answer = txtAnswer.getText();
        if (answer.trim().length() <= 0) {
            JOptionPane.showMessageDialog(this, "Please enter a response.");
            return;
        }
        countdownMeter.setActive(false);
        processQuestionOver();
        txtAnswer.setText(null);
        if (txtChatLine.getText().length() > 0) {
            txtChatLine.requestFocus();
        } else {
            txtAnswer.requestFocus();
        }

        final Address giver = quizChannel.getView().getMembers().firstElement();
        sendAsync(quizChannel, giver, new AnswerMsg(txtAnswer.getText()));
    }//GEN-LAST:event_btnSubmitActionPerformed

    private void restoreChat() {
        btnSendChatLine.setEnabled(getQuizState().isChatEnabled());
    }

    /** Exit the Application */
    private final void exitForm(final WindowEvent evt) {//GEN-FIRST:event_exitForm
        try {
            deregister();
        } catch (Exception exc) {
            exc.printStackTrace();
        }
        System.exit(0);
    }//GEN-LAST:event_exitForm

    final void setFrameTitle() {
        final Object[] messageArguments = { takerName, getQuizName(), "?" };
        final MessageFormat formatter = new MessageFormat(Resources.getString("clientTitle"));
        setTitle(formatter.format(messageArguments));
    }

    private void deregister() {
        try {
            log.debug("Disconnecting");
            quizChannel.disconnect();
            log.debug("Closing");
            quizChannel.close();
            log.debug("Done");
        } catch (Exception e) {
            ErrorHandler.handleException(e);
        }
    }

    /**
     * @see java.awt.event.FocusListener#focusGained(java.awt.event.FocusEvent)
     */
    public final void focusGained(final FocusEvent e) {
        if (e.getID() == FocusEvent.FOCUS_GAINED && e.getComponent() == txtChatLine) {
            getRootPane().setDefaultButton(btnSendChatLine);
        }

        else if (e.getID() == FocusEvent.FOCUS_GAINED && e.getComponent() == txtAnswer) {
            getRootPane().setDefaultButton(btnSubmit);
        }
    }

    /**
     * @see java.awt.event.FocusListener#focusLost(java.awt.event.FocusEvent)
     */
    public final void focusLost(@SuppressWarnings("unused") final FocusEvent e) {
        // Ignore
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        jLabel4 = new javax.swing.JLabel();
        pnlQA = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        txtAnswer = new javax.swing.JTextField();
        btnSubmit = new javax.swing.JButton();
        lblQuestion = new javax.swing.JLabel();
        countdownMeter = new com.dbschools.gui.CountdownMeter();
        pnlChat = new javax.swing.JPanel();
        txtChatLine = new javax.swing.JTextField();
        btnSendChatLine = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        pnlSideBySide = new javax.swing.JPanel();
        pnlPlayers = new javax.swing.JPanel();
        pnlMessages = new javax.swing.JPanel();
        scpMessages = new javax.swing.JScrollPane();
        lstMessages = new javax.swing.JList();

        jLabel4.setText("jLabel4");

        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                exitForm(evt);
            }
        });
        getContentPane().setLayout(new java.awt.GridBagLayout());

        java.util.ResourceBundle bundle = java.util.ResourceBundle
                .getBundle("com/dbschools/quickquiz/client/taker/Bundle"); // NOI18N
        pnlQA.setBorder(javax.swing.BorderFactory.createTitledBorder(bundle.getString("qa"))); // NOI18N
        pnlQA.setLayout(new java.awt.GridBagLayout());

        jLabel2.setDisplayedMnemonic('a');
        jLabel2.setLabelFor(txtAnswer);
        jLabel2.setText(bundle.getString("a")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        pnlQA.add(jLabel2, gridBagConstraints);

        txtAnswer.setColumns(30);
        txtAnswer.setFont(new java.awt.Font("Serif", 0, 14));
        txtAnswer.setToolTipText(bundle.getString("tttAnswer")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 3.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        pnlQA.add(txtAnswer, gridBagConstraints);

        btnSubmit.setMnemonic('s');
        btnSubmit.setText(bundle.getString("submitAnswer")); // NOI18N
        btnSubmit.setEnabled(false);
        btnSubmit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnSubmitActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        pnlQA.add(btnSubmit, gridBagConstraints);

        lblQuestion.setFont(new java.awt.Font("Tahoma", 1, 14)); // NOI18N
        lblQuestion.setText(bundle.getString("waitingForNextQuestion")); // NOI18N
        lblQuestion.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
        lblQuestion.setPreferredSize(new java.awt.Dimension(179, 26));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.insets = new java.awt.Insets(0, 2, 2, 2);
        pnlQA.add(lblQuestion, gridBagConstraints);

        countdownMeter.setToolTipText("Displays the amount of time left for answering the question");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        pnlQA.add(countdownMeter, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        getContentPane().add(pnlQA, gridBagConstraints);

        pnlChat.setBorder(javax.swing.BorderFactory.createTitledBorder(bundle.getString("chat"))); // NOI18N
        pnlChat.setLayout(new java.awt.GridBagLayout());

        txtChatLine.setColumns(40);
        txtChatLine.setToolTipText(bundle.getString("tttChatMessage")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 2, 0, 2);
        pnlChat.add(txtChatLine, gridBagConstraints);

        btnSendChatLine.setMnemonic('d');
        btnSendChatLine.setText(bundle.getString("sendChatLine")); // NOI18N
        btnSendChatLine.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnSendChatLineActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 2, 0, 2);
        pnlChat.add(btnSendChatLine, gridBagConstraints);

        jLabel1.setDisplayedMnemonic('m');
        jLabel1.setLabelFor(txtChatLine);
        jLabel1.setText(bundle.getString("chatMessage")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 2, 0, 2);
        pnlChat.add(jLabel1, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(5, 2, 2, 2);
        getContentPane().add(pnlChat, gridBagConstraints);

        pnlSideBySide.setLayout(new java.awt.GridBagLayout());

        pnlPlayers.setBorder(javax.swing.BorderFactory.createTitledBorder(bundle.getString("takers"))); // NOI18N
        pnlPlayers.setMaximumSize(new java.awt.Dimension(250, 99999));
        pnlPlayers.setMinimumSize(new java.awt.Dimension(100, 50));
        pnlPlayers.setPreferredSize(new java.awt.Dimension(250, 400));
        pnlPlayers.setLayout(new javax.swing.BoxLayout(pnlPlayers, javax.swing.BoxLayout.LINE_AXIS));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.5;
        gridBagConstraints.weighty = 0.6;
        gridBagConstraints.insets = new java.awt.Insets(5, 2, 2, 2);
        pnlSideBySide.add(pnlPlayers, gridBagConstraints);

        pnlMessages.setBorder(javax.swing.BorderFactory.createTitledBorder(bundle.getString("messages"))); // NOI18N
        pnlMessages.setLayout(new javax.swing.BoxLayout(pnlMessages, javax.swing.BoxLayout.LINE_AXIS));

        lstMessages.setFont(new java.awt.Font("SansSerif", 0, 10));
        lstMessages.setModel(new MessagesListModel());
        scpMessages.setViewportView(lstMessages);

        pnlMessages.add(scpMessages);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.5;
        gridBagConstraints.weighty = 0.4;
        gridBagConstraints.insets = new java.awt.Insets(5, 2, 0, 2);
        pnlSideBySide.add(pnlMessages, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        getContentPane().add(pnlSideBySide, gridBagConstraints);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnSendChatLine;
    private javax.swing.JButton btnSubmit;
    private com.dbschools.gui.CountdownMeter countdownMeter;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel lblQuestion;
    private javax.swing.JList lstMessages;
    private javax.swing.JPanel pnlChat;
    private javax.swing.JPanel pnlMessages;
    private javax.swing.JPanel pnlPlayers;
    private javax.swing.JPanel pnlQA;
    private javax.swing.JPanel pnlSideBySide;
    private javax.swing.JScrollPane scpMessages;
    private javax.swing.JTextField txtAnswer;
    private javax.swing.JTextField txtChatLine;
    // End of variables declaration//GEN-END:variables

}