/*
* 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.Dimension;
import java.awt.event.ActionEvent;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingConstants;
import javax.swing.border.EtchedBorder;
import jmemorize.core.Card;
import jmemorize.core.Category;
import jmemorize.core.Main;
import jmemorize.core.learn.LearnSession;
import jmemorize.core.learn.LearnSessionObserver;
import jmemorize.core.learn.LearnSettings;
import jmemorize.core.learn.LearnSession.LearnCardObserver;
import jmemorize.gui.LC;
import jmemorize.gui.Localization;
import jmemorize.gui.swing.ColorConstants;
import jmemorize.gui.swing.SelectionProvider;
import jmemorize.gui.swing.actions.AbstractAction2;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
/**
* The panel that shows learning sessions (learning preferences are handled by
* the LearnSettings classes.
*
* @author djemili
*/
public class LearnPanel extends JPanel implements SelectionProvider,
LearnSessionObserver, LearnCardObserver
{
private class StopAction extends AbstractAction2
{
public StopAction()
{
setName(Localization.get(LC.LEARN_STOP));
}
public void actionPerformed(ActionEvent e)
{
m_session.endLearning();
}
}
private LearnSession m_session;
private Card m_currentCard;
private TimerPanel m_timerPanel = new TimerPanel();
private CardCounterPanel m_cardCounterPanel = new CardCounterPanel();
private JLabel m_flippedLabel = new JLabel(
Localization.get(LC.LEARN_FLIPPED),
new ImageIcon(getClass().getResource("/resource/icons/card_flipped.gif")), //$NON-NLS-1$
SwingConstants.CENTER
);
// member variables so we can make them invisible
private JLabel m_currentCardProgressLabel;
private JProgressBar m_currentCardProgressBar;
private boolean m_isPartialProgressMode;
private StatusBar m_statusBar;
private List<SelectionObserver> m_selectionListeners = new LinkedList<SelectionObserver>();
public LearnPanel()
{
initComponents();
Main.getInstance().addLearnSessionObserver(this);
}
/* (non-Javadoc)
* @see jmemorize.core.LearnSessionObserver
*/
public void sessionStarted(LearnSession session)
{
m_session = session;
m_session.addObserver(this);
LearnSettings settings = session.getSettings();
if (settings.isTimeLimitEnabled())
{
m_timerPanel.start(session, settings.getTimeLimit() * 60);
}
else
{
m_timerPanel.start(session);
}
// test always showing the extent progress bar
int targetCards = m_session.getCardsLeft().size();
if (session.getSettings().isCardLimitEnabled())
{
targetCards = Math.min(session.getSettings().getCardLimit(), targetCards);
}
m_cardCounterPanel.start(targetCards);
int sidesToTest = settings.getAmountToTest(true) +
settings.getAmountToTest(false);
m_isPartialProgressMode = settings.getSidesMode() == LearnSettings.SIDES_BOTH &&
(sidesToTest > 1);
m_currentCardProgressLabel.setVisible(m_isPartialProgressMode);
m_currentCardProgressBar.setVisible(m_isPartialProgressMode);
m_currentCardProgressBar.setMinimum(0);
m_currentCardProgressBar.setMaximum(sidesToTest);
}
/* (non-Javadoc)
* @see jmemorize.core.LearnSessionObserver
*/
public void sessionEnded(LearnSession session)
{
m_timerPanel.stop();
if (m_statusBar != null)
{
m_statusBar.setLeftText(""); //$NON-NLS-1$
}
}
/**
* 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_flippedLabel.setVisible(flipped);
for (SelectionObserver listener : m_selectionListeners)
{
listener.selectionChanged(this);
}
updateStatusBar();
updateProgressBars();
}
/* (non-Javadoc)
* @see jmemorize.gui.swing.SelectionProvider
*/
public List<Card> getRelatedCards()
{
List<Card> l = new ArrayList<Card>();
l.addAll(m_session.getCheckedCards());
return l;
}
/* (non-Javadoc)
* @see jmemorize.gui.swing.SelectionProvider
*/
public Category getCategory()
{
return m_session.getCategory();
}
/* (non-Javadoc)
* @see jmemorize.gui.swing.SelectionProvider
*/
public List<Category> getSelectedCategories()
{
return null;
}
/* (non-Javadoc)
* @see jmemorize.gui.swing.SelectionProvider
*/
public List<Card> getSelectedCards()
{
List<Card> list = new ArrayList<Card>(1);
list.add(m_currentCard);
return list.size() > 0 ? list : null;
}
/* (non-Javadoc)
* @see jmemorize.gui.swing.SelectionProvider
*/
public void addSelectionObserver(SelectionObserver observer)
{
m_selectionListeners.add(observer);
}
/* (non-Javadoc)
* @see jmemorize.gui.swing.SelectionProvider
*/
public void removeSelectionObserver(SelectionObserver observer)
{
m_selectionListeners.remove(observer);
}
/* (non-Javadoc)
* @see jmemorize.gui.swing.SelectionProvider
*/
public JComponent getDefaultFocusOwner()
{
return this;
}
/* (non-Javadoc)
* @see jmemorize.gui.swing.SelectionProvider
*/
public JFrame getFrame()
{
return Main.getInstance().getFrame();
}
/**
* Set the status bar for use with this panel.
*/
public void setStatusBar(StatusBar statusBar)
{
m_statusBar = statusBar;
}
private void initComponents()
{
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(buildSidebarPanel(), BorderLayout.WEST);
mainPanel.add(new QuizPanel(), BorderLayout.CENTER);
setLayout(new BorderLayout());
add(mainPanel, BorderLayout.CENTER);
}
private JPanel buildSidebarPanel()
{
m_timerPanel.setBackground(ColorConstants.SIDEBAR_COLOR);
m_timerPanel.setPreferredSize(new Dimension(140, 22));
m_currentCardProgressLabel = new JLabel(Localization.getEmpty(LC.LEARN_CARD));
m_currentCardProgressLabel.setVisible(false);
m_currentCardProgressBar = new JProgressBar();
m_currentCardProgressBar.setMinimum(0);
m_currentCardProgressBar.setMaximum(2);
m_currentCardProgressBar.setValue(0);
m_currentCardProgressBar.setVisible(false);
// force to solid rendering (default is ugly stripe)
m_currentCardProgressBar.setStringPainted(true);
m_currentCardProgressBar.setPreferredSize(new Dimension(140, 22));
m_cardCounterPanel.setBackground(ColorConstants.SIDEBAR_COLOR);
JButton stopLearningButton = new JButton(new StopAction());
// build it using FormLayout
FormLayout layout = new FormLayout(
"center:170px:grow", // columns //$NON-NLS-1$
"9dlu, p, 3dlu, p, 12dlu, p, 3dlu, p, 12dlu, p, 3dlu, " + //$NON-NLS-1$
"p, 12dlu, fill:p:grow, 5dlu, p, 5px"); // rows //$NON-NLS-1$
CellConstraints cc = new CellConstraints();
DefaultFormBuilder builder = new DefaultFormBuilder(layout);
builder.addLabel(Localization.get(LC.LEARN_TIMER), cc.xy(1, 2));
builder.add(m_timerPanel, cc.xy(1, 4));
String title = Localization.get(LC.LEARN_SESSION, LC.LEARN_CARD_COUNTER);
builder.addLabel(title, cc.xy(1, 6));
builder.add(m_cardCounterPanel, cc.xy(1, 8));
builder.add(m_currentCardProgressLabel, cc.xy(1, 10));
builder.add(m_currentCardProgressBar, cc.xy(1, 12));
builder.add(m_flippedLabel, cc.xy(1, 14));
builder.add(stopLearningButton, cc.xy(1, 16));
JPanel sidePanel = builder.getPanel();
sidePanel.setBackground(ColorConstants.SIDEBAR_COLOR);
sidePanel.setBorder(new EtchedBorder());
return sidePanel;
}
private void updateProgressBars()
{
int cardsLearned = m_session.getNCardsLearned();
int cardsPartiallyLearned = m_session.getNCardsPartiallyLearned();
m_cardCounterPanel.setCardsPassed(cardsLearned, cardsPartiallyLearned);
if (!m_isPartialProgressMode || m_currentCard == null)
return;
int amtLearned = m_currentCard.getLearnedAmount(true) + m_currentCard.getLearnedAmount(false);
m_currentCardProgressBar.setValue(amtLearned);
m_currentCardProgressBar.setString(amtLearned + " / " + //$NON-NLS-1$
m_currentCardProgressBar.getMaximum());
}
private void updateStatusBar()
{
if (m_statusBar != null)
{
Object[] args = {
Localization.get(LC.STATUS_LEARNING_CATEGORY),
m_session.getCategory().getName(),
Localization.get(LC.STATUS_CARDS_LEFT),
new Integer(m_session.getCardsLeft().size())};
MessageFormat form = new MessageFormat("{0}: {1} {2}: {3}"); //$NON-NLS-1$
m_statusBar.setLeftText(form.format(args));
}
}
}