Java tutorial
/* * jMemorize - Learning made easy (and fun) - A Leitner flashcards tool * Copyright(C) 2004-2008 Riad Djemili and contributors * * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package jmemorize.gui.swing.panels; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.border.EmptyBorder; import javax.swing.border.EtchedBorder; import jmemorize.core.Card; import jmemorize.core.CardSide; import jmemorize.core.Category; import jmemorize.core.CategoryObserver; import jmemorize.core.Events; import jmemorize.core.Main; import jmemorize.core.Settings; import jmemorize.core.learn.LearnSession; import jmemorize.core.learn.LearnSessionObserver; import jmemorize.core.learn.LearnSession.LearnCardObserver; import jmemorize.gui.LC; import jmemorize.gui.Localization; import jmemorize.gui.swing.CardFont; import jmemorize.gui.swing.Quiz; import jmemorize.gui.swing.CardFont.FontType; import jmemorize.gui.swing.actions.AbstractAction2; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; /** * @author djemili */ public class QuizPanel extends JPanel implements Events, LearnCardObserver, CategoryObserver, LearnSessionObserver { private abstract class AbstractLearnAction extends AbstractAction2 { private boolean m_shortCutAdded = false; protected void setFocusedWindowShortcut(String action, char key) { getInputMap(JButton.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(key), action); getActionMap().put(action, this); if (!m_shortCutAdded) { String name = (String) getValue(NAME); setName(String.format("<html>%s <font color=gray>(%s)</font></html>", name, key)); m_shortCutAdded = true; } } } private class ShowAction extends AbstractLearnAction { public ShowAction() { setName(Localization.get(LC.LEARN_SHOW)); setFocusedWindowShortcut("showButton", 'a'); //$NON-NLS-1$ } public void actionPerformed(ActionEvent e) { if (m_isShowQuestion) showAnswer(); } } private class SkipAction extends AbstractLearnAction { public SkipAction() { setName(Localization.get(LC.LEARN_SKIP)); setFocusedWindowShortcut("skipButton", 's'); //$NON-NLS-1$ } public void actionPerformed(ActionEvent e) { if (m_isShowQuestion) m_session.cardSkipped(); } } private class YesAction extends AbstractLearnAction { public YesAction() { setName(Localization.get(LC.LEARN_YES)); setFocusedWindowShortcut("yesButton", 'q'); //$NON-NLS-1$ } public void actionPerformed(ActionEvent e) { if (m_isShowAnswer) m_session.cardChecked(true, m_showFlipped); } } private class NoAction extends AbstractLearnAction { public NoAction() { setName(Localization.get(LC.LEARN_NO)); setFocusedWindowShortcut("noButton", 'w'); //$NON-NLS-1$ } public void actionPerformed(ActionEvent e) { if (m_isShowAnswer) m_session.cardChecked(false, m_showFlipped); } } private static final String ANSWER_CARD = "answerCard"; //$NON-NLS-1$ private static final String QUESTION_CARD = "questionCard"; //$NON-NLS-1$ // swing elements private JButton m_showButton = new JButton(new ShowAction()); private JButton m_yesButton = new JButton(new YesAction()); private TwoSidesCardPanel m_questionCardPanel = new TwoSidesCardPanel(false, false); private Quiz m_quiz = new ThinkQuiz(); private JPanel m_answerBarPanel = buildAnswerButtonBar(); private JPanel m_questionBarPanel = buildQuestionButtonBar(); private JPanel m_barPanel = new JPanel(); private LearnSession m_session; private Card m_currentCard; private boolean m_showFlipped; private boolean m_frontWasVisible; private JCheckBox m_categoryCheckBox = new JCheckBox(Localization.get(LC.LEARN_SHOW_CATEGORY)); private JTextField m_categoryField = new JTextField(); private boolean m_isShowQuestion; private boolean m_isShowAnswer; private static String PREFS_SHOW_CARD_CATEGORY = "show.card-category"; //$NON-NLS-1$ public QuizPanel() { initComponents(); Main.getInstance().addLearnSessionObserver(this); } /* (non-Javadoc) * @see jmemorize.core.learn.LearnSessionObserver */ public void sessionStarted(LearnSession session) { m_session = session; session.addObserver(this); m_session.getCategory().addObserver(this); } /* (non-Javadoc) * @see jmemorize.core.learn.LearnSessionObserver */ public void sessionEnded(LearnSession session) { m_isShowQuestion = false; m_isShowAnswer = false; m_session.getCategory().removeObserver(this); } /** * Show the card. * * @param flipped <code>true</code> if card should be shown with reversed * sides (that is the frontside will be shown as flipside and vice versa) * <code>false</code> otherwise. */ public void nextCardFetched(Card card, boolean flipped) { m_currentCard = card; m_showFlipped = flipped; updateFonts(); updateCardSidePanels(); updateCategoryField(); showQuestion(); } /* (non-Javadoc) * @see jmemorize.core.CategoryObserver */ public void onCardEvent(int type, Card card, Category category, int deck) { if (card == m_currentCard) { if (type == EDITED_EVENT) updateCardSidePanels(); if (type == MOVED_EVENT) updateCategoryField(); } } /* (non-Javadoc) * @see jmemorize.core.CategoryObserver */ public void onCategoryEvent(int type, Category category) { assert false; // no category events should occur while learning } private void updateFonts() { CardFont frontFont = Settings.loadFont(FontType.LEARN_FRONT); CardFont flipFont = Settings.loadFont(FontType.LEARN_FLIP); CardFont questionFont = !m_showFlipped ? frontFont : flipFont; CardFont answerFont = !m_showFlipped ? flipFont : frontFont; m_questionCardPanel.fontChanged(FontType.CARD_FRONT, questionFont); m_questionCardPanel.fontChanged(FontType.CARD_FLIP, answerFont); m_quiz.setQuestionFont(questionFont); m_quiz.setAnswerFont(answerFont); } private void initComponents() { m_questionCardPanel.setEditable(false); m_questionCardPanel.setBorder(new EmptyBorder(5, 10, 5, 10)); m_questionCardPanel.addCardSide(Localization.get(LC.FLIPSIDE), m_quiz.getVisual()); setLayout(new BorderLayout()); m_barPanel.setLayout(new CardLayout()); m_barPanel.add(m_questionBarPanel, QUESTION_CARD); m_barPanel.add(m_answerBarPanel, ANSWER_CARD); JPanel mainCardPanel = new JPanel(new BorderLayout()); mainCardPanel.setBorder(new EtchedBorder()); JPanel catPanel = buildCategoryPanel(); mainCardPanel.add(catPanel, BorderLayout.NORTH); mainCardPanel.add(m_questionCardPanel, BorderLayout.CENTER); mainCardPanel.add(m_barPanel, BorderLayout.SOUTH); add(mainCardPanel, BorderLayout.CENTER); } /** * Fills the text panes with the card side texts of the currently shown * card. */ private void updateCardSidePanels() { if (m_currentCard != null) { CardSide questionSide = !m_showFlipped ? m_currentCard.getFrontSide() : m_currentCard.getBackSide(); CardSide answerSide = !m_showFlipped ? m_currentCard.getBackSide() : m_currentCard.getFrontSide(); m_questionCardPanel.setTextSides(questionSide.getText(), answerSide.getText()); m_questionCardPanel.setImages(questionSide.getImages(), answerSide.getImages()); m_quiz.showQuestion(answerSide); } m_questionCardPanel.setFlipped(m_showFlipped); } private void updateCategoryField() { m_categoryField.setEnabled(m_categoryCheckBox.isSelected()); m_categoryField.setText(m_categoryCheckBox.isSelected() ? m_currentCard.getCategory().getPath() + " (" + m_currentCard.getLevel() + ")" //$NON-NLS-1$//$NON-NLS-2$ : ""); //$NON-NLS-1$ } private void showQuestion() { if (m_isShowAnswer) { m_frontWasVisible = m_questionCardPanel.isCardSideVisible(0) && m_questionCardPanel.isCardSideVisible(1); } m_questionCardPanel.setCardSideVisible(0, true); m_questionCardPanel.setCardSideVisible(1, false); m_questionCardPanel.setCardSideEnabled(1, false); ((CardLayout) m_barPanel.getLayout()).show(m_barPanel, QUESTION_CARD); m_isShowQuestion = true; m_isShowAnswer = false; m_showButton.requestFocus(); } private void showAnswer() { m_questionCardPanel.setCardSideVisible(0, m_frontWasVisible); m_questionCardPanel.setCardSideVisible(1, true); m_questionCardPanel.setCardSideEnabled(1, true); ((CardLayout) m_barPanel.getLayout()).show(m_barPanel, ANSWER_CARD); m_isShowQuestion = false; m_isShowAnswer = true; float result = m_quiz.showAnswer(); if (result >= 0) // HACK { m_session.cardChecked((result >= 0.5f), m_showFlipped); } m_yesButton.requestFocus(); } private JPanel buildCategoryPanel() { // prepare category field and checkbox m_categoryCheckBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { boolean showCategory = m_categoryCheckBox.isSelected(); Main.USER_PREFS.putBoolean(PREFS_SHOW_CARD_CATEGORY, showCategory); updateCategoryField(); } }); m_categoryField.setEditable(false); boolean showCat = Main.USER_PREFS.getBoolean(PREFS_SHOW_CARD_CATEGORY, true); m_categoryCheckBox.setSelected(showCat); // build it using the forms layout FormLayout layout = new FormLayout("38dlu, 3dlu, p:grow, 3dlu, right:p", // columns //$NON-NLS-1$ "20px"); // rows //$NON-NLS-1$ CellConstraints cc = new CellConstraints(); DefaultFormBuilder builder = new DefaultFormBuilder(layout); builder.setBorder(new EmptyBorder(10, 10, 7, 10)); builder.addLabel(Localization.get(LC.CATEGORY), cc.xy(1, 1)); builder.add(m_categoryField, cc.xy(3, 1)); builder.add(m_categoryCheckBox, cc.xy(5, 1)); return builder.getPanel(); } private JPanel buildQuestionButtonBar() { JButton skipButton = new JButton(new SkipAction()); // build it using forms layout FormLayout layout = getBottomFormLayout(); CellConstraints cc = new CellConstraints(); DefaultFormBuilder builder = new DefaultFormBuilder(layout); builder.setBorder(new EmptyBorder(5, 5, 5, 10)); builder.addLabel(m_quiz.getHelpText(), cc.xy(1, 1)); builder.add(m_showButton, cc.xy(3, 1)); builder.add(skipButton, cc.xy(5, 1)); return builder.getPanel(); } private JPanel buildAnswerButtonBar() { // preapre no button JButton noButton = new JButton(new NoAction()); // build it using forms layout FormLayout layout = getBottomFormLayout(); CellConstraints cc = new CellConstraints(); DefaultFormBuilder builder = new DefaultFormBuilder(layout); builder.setBorder(new EmptyBorder(5, 5, 5, 10)); builder.addLabel(Localization.get(LC.LEARN_DID_YOU_KNOW), cc.xy(1, 1)); builder.add(m_yesButton, cc.xy(3, 1)); builder.add(noButton, cc.xy(5, 1)); return builder.getPanel(); } private FormLayout getBottomFormLayout() { return new FormLayout("right:p:grow, 3dlu, 80dlu, 3dlu, 80dlu", //$NON-NLS-1$ "p"); //$NON-NLS-1$ } }