Package org.jsurveylib.gui.swing

Source Code of org.jsurveylib.gui.swing.SurveyPanel

/**
* This file is part of JSurveyLib.
*
* JSurveyLib is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JSurveyLib 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JSurveyLib.  If not, see <http://www.gnu.org/licenses/>.
**/

package org.jsurveylib.gui.swing;

import org.jsurveylib.ClientSurvey;
import org.jsurveylib.Survey;
import org.jsurveylib.gui.swing.renderer.PageRenderer;
import org.jsurveylib.gui.swing.util.ChooserUtil;
import org.jsurveylib.model.Page;
import org.jsurveylib.model.SurveyElement;
import org.jsurveylib.model.listeners.AnswerListener;
import org.jsurveylib.model.listeners.PageListener;
import org.jsurveylib.model.listeners.SurveyResetListener;
import org.jsurveylib.model.question.InsertQuestionListener;
import org.jsurveylib.model.question.Question;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.io.IOException;

/**
* This class displays the Survey object.  It extends JPanel.  Here is an example of how to add a SurveyPanel to your JFrame:
* <pre><code>
*               try {
*                   ClientSurvey survey = new Survey("surveyGettingStarted.xml");
*                   SurveyPanel surveyPanel = new SurveyPanel(survey);
*                   survey.addSurveyListener(this);
*                   frame.setLayout(new BorderLayout());
*                   frame.add(surveyPanel, BorderLayout.CENTER);
*                   frame.setJMenuBar(new SurveyMenu(survey, frame));
*               } catch (Exception e) {
*                   e.printStackTrace();
*               }
*               </code></pre>
* <p/>
* <b>The Survey, ClientSurvey, SurveyPanel and the SurveyAdapter are the ONLY objects that the client should interact with directly.  Even then, there
* may be public methods in this class that are marked "for internal use only".  Methods marked "for
* internal use only" may be renamed, removed or replaced in future versions.  Because of this uncertain future,
* it is highly recommended you don't use these methods: Your application may not compile when you upgrade.
* Most other classes are marked "for internal use only" but even if they aren't, these are the only
* classes that you should be interacting with.</b>
* <p/>
* Copyright (c)2007, Daniel Kaplan
*
* @author Daniel Kaplan
* @since 7.10.4
*/
public class SurveyPanel extends JPanel implements AnswerListener, PageListener, InsertQuestionListener, SurveyResetListener {

    /**
     * <u><b><font color="red">FOR INTERNAL USE ONLY.</font></b></u>.  These will likely disappear in the future.
     */
    public static final Font FONT_SURVEY_TITLE = new Font("SansSerif", Font.BOLD, 16);
    /**
     * <u><b><font color="red">FOR INTERNAL USE ONLY.</font></b></u>  These will likely disappear in the future.
     */
    public static final Font FONT_PAGE_TITLE = new Font("SansSerif", Font.PLAIN, 14);
    /**
     * <u><b><font color="red">FOR INTERNAL USE ONLY.</font></b></u>  These will likely disappear in the future.
     */
    public static final Font FONT_LABEL = new Font("SansSerif", Font.PLAIN, 12);
    /**
     * <u><b><font color="red">FOR INTERNAL USE ONLY.</font></b></u>  These will likely disappear in the future.
     */
    public static final Font FONT_QUESTION_NUMBER = new Font("SansSerif", Font.BOLD, 12);
    /**
     * <u><b><font color="red">FOR INTERNAL USE ONLY.</font></b></u>  These will likely disappear in the future.
     */
    public static final Font FONT_QUESTION_TEXT = new Font("SansSerif", Font.PLAIN, 12);
    /**
     * <u><b><font color="red">FOR INTERNAL USE ONLY.</font></b></u>  These will likely disappear in the future.
     */
    public static final Font FONT_QUESTION_ANSWER = new Font("SansSerif", Font.PLAIN, 12);

    // Page management
    /**
     * The panel containing the question objects
     */
    private JPanel pageArea;
    /**
     * The card layout used to switch between pages
     */
    private CardLayout pager;


    /**
     * The vector of pages
     */
    private List<PageRenderer> pageComponents = new ArrayList<PageRenderer>();

    /**
     * The label indicating the current page
     */
    private JLabel pageNumberLabel;

    /**
     * Navigation
     */
    private JButton previousButton;
    private JButton nextButton;
    private JButton finishButton;

    private Survey survey;

    /**
     * This will initialize the SurveyPanel object.  The Panel queries the survey object for
     * its content and renders it on the screen.  The Survey will start on the first page.
     *
     * @param survey The survey object that is rendered by this SurveyPanel.
     */
    public SurveyPanel(ClientSurvey survey) {
        this.survey = (Survey) survey;
        this.survey.addPageListener(this);
        this.survey.addInsertQuestionListener(this);
        this.survey.addSurveyResetListener(this);
        reset();    //this will initialize the UI
    }

    private void reset() {
        pageComponents.clear();
        createUI();
        switchPage();   //go to the first page
    }

    /**
     * Create the User Interface of the survey
     */
    private void createUI() {
        removeAll();
        //basic configuration
        setLayout(new BorderLayout(12, 12));
        setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));

        //the title of the survey
        String title = survey.getTitle();
        if (title != null && !title.equals("")) {
            JLabel titleLabel = new JLabel(title);
            titleLabel.setFont(SurveyPanel.FONT_SURVEY_TITLE);
            add(titleLabel, BorderLayout.NORTH);
        }

        //the central area (with the questions) is warpped within a scrollpane
        pageArea = new JPanel();
        pager = new CardLayout();
        pageArea.setLayout(pager);

        //create the survey pages
        createPages();
        for (int i = 0; i < pageComponents.size(); i++) {
            JScrollPane scroll = new JScrollPane(pageComponents.get(i),
                    JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                    JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            pageArea.add(Integer.toString(i), scroll);
        }

        //scrollbar (for the case when we don't have enough space for the whole page)
        add(pageArea, BorderLayout.CENTER);

        //control buttons
        JPanel panButtons = new JPanel(new GridLayout(1, 0, 6, 6));
        previousButton = new JButton(survey.getStrings().getPreviousString());
        previousButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                survey.goToPreviousPage();
            }
        });
        panButtons.add(previousButton);
        nextButton = new JButton(survey.getStrings().getNextString());
        nextButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                survey.goToNextPage();
            }
        });
        panButtons.add(nextButton);
        finishButton = new JButton(survey.getStrings().getFinishString());
        finishButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                if (survey.saveToFileOnFinish() && survey.isDirty()) {
                    try {
                        saveChanges();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                } else {
                    survey.finish();
                }
            }
        });
        panButtons.add(finishButton);

        JPanel statusArea = new JPanel(new BorderLayout());
        statusArea.add(panButtons, BorderLayout.EAST);
        pageNumberLabel = new JLabel();
        pageNumberLabel.setFont(new Font("SansSerif", Font.PLAIN, 12));
        statusArea.add(pageNumberLabel, BorderLayout.WEST);
        add(statusArea, BorderLayout.SOUTH);

        if (pageComponents.size() == 1) {
            previousButton.setVisible(false);
            nextButton.setVisible(false);
            pageNumberLabel.setVisible(false);
        }
        this.invalidate();
        this.validate();
    }

    private void saveChanges() throws IOException {
        if (survey.getWorkingFilePath() != null) {
            int result = JOptionPane.showConfirmDialog(null, survey.getStrings().getSaveToWorkingFileNotificationString() + survey.getWorkingFilePath(), survey.getStrings().getUnsavedChangesString(), JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE);
            if (result == JOptionPane.OK_OPTION) {
                survey.saveXMLAnswers(survey.getWorkingFilePath());
                survey.finish();
            }
        } else {
            int result = JOptionPane.showConfirmDialog(null, survey.getStrings().getSaveToNewFileNotificationString(), survey.getStrings().getUnsavedChangesString(), JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE);
            if (result == JOptionPane.OK_OPTION) {
                //this will fail if a JFrame is not used
                ChooserUtil.saveSurveyChooser((JFrame) SwingUtilities.getRoot(this), survey);
                if (!survey.isDirty()) {
                    //if the survey isn't dirty, that means the user saved with the save survey chooser
                    survey.finish();
                }
            }
        }
    }

    /**
     * Configure the buttons (set them enabled / disabled)
     */
    private void configButtons() {
        previousButton.setEnabled(survey.isPreviousPageAvailable());
        nextButton.setEnabled(survey.isNextPageAvailable());
        finishButton.setEnabled(survey.isLastPageAndComplete());
    }

    /**
     * Break the question to the different pages
     */
    private void createPages() {

        for (Page page : survey.getPages()) {

            String pageLabel = page.getLabel().trim();
            PageRenderer pageRenderer = startNewPage(pageLabel);

            //add the questions
            for (SurveyElement element : page.getSurveyElements()) {
                pageRenderer.addElement(element);
                if (element instanceof Question) {
                    ((Question) element).addAnswerListener(this);
                }
            }
            pageRenderer.packElements();
        }
    }

    /**
     * Create a new page object and return its renderer
     * @return The PageRenderer of this page
     * @param pageLabel The label of this page
     */
    private PageRenderer startNewPage(String pageLabel) {
        PageRenderer cPage = new PageRenderer(survey.getStrings());
        cPage.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), pageLabel));
        pageComponents.add(cPage);
        return cPage;
    }

    /**
     * <u><b><font color="red">FOR INTERNAL USE ONLY.</font></b></u>  This will be called when a question's answer has changed.
     * The panel will react by enabling/disabling its buttons.  This is for internal use because only JSurveyLib should be calling
     * this method.
     *
     * @param question       The question who's answer has changed
     * @param evaluateScript This boolean is ignored
     */
    public void answerChanged(Question question, boolean evaluateScript) {
        configButtons();
    }

    /**
     * <u><b><font color="red">FOR INTERNAL USE ONLY.</font></b></u>  This method will be called to inform the
     * panel that it should display a different page.  This is internal because only the Survey object should be calling
     * this method.
     */
    public void currentPageChanged() {
        switchPage();
    }

    private void switchPage() {
        pager.show(pageArea, Integer.toString(survey.getCurrentPageNumber()));
        pageNumberLabel.setText(survey.getStrings().getPageString() + " " + (survey.getCurrentPageNumberExcludingSkipped() + 1) + " " + survey.getStrings().getOfString() + " " + survey.getTotalPagesExcludingSkipped());
        configButtons();
    }

    public void questionInserted(Question question, int page, int row) {
        question.addAnswerListener(this);
        pageComponents.get(page).insertQuestion(question, row);
    }

    public void surveyReset() {
        reset();
    }
}
TOP

Related Classes of org.jsurveylib.gui.swing.SurveyPanel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.