Java tutorial
/* * jMemorize - Learning made easy (and fun) - A Leitner flashcards tool * Copyright(C) 2004-2006 Riad Djemili * * 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.frames; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.ButtonGroup; import javax.swing.DefaultComboBoxModel; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTextPane; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.border.EmptyBorder; import javax.swing.border.EtchedBorder; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; import javax.swing.text.DefaultEditorKit; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.factories.ButtonBarFactory; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; import jmemorize.core.Card; import jmemorize.core.Category; import jmemorize.core.CategoryObserver; import jmemorize.core.Events; import jmemorize.core.Main; import jmemorize.core.Main.ProgramEndObserver; import jmemorize.core.SearchTool; import jmemorize.core.Settings; import jmemorize.gui.LC; import jmemorize.gui.Localization; import jmemorize.gui.swing.actions.AbstractAction2; import jmemorize.gui.swing.panels.StatusBar; import jmemorize.gui.swing.widgets.CardTable; import jmemorize.gui.swing.widgets.CategoryComboBox; import jmemorize.util.EscapableFrame; import jmemorize.util.RecentItems; /** * A frame that shows search options and a card table as results view. * * @author djemili */ public class FindFrame extends EscapableFrame implements CategoryObserver, ProgramEndObserver { private final static String FRAME_ID = "findframe"; private CardTable m_cardTable = new CardTable(this, Main.USER_PREFS.node("find.table"), //$NON-NLS-1$ new int[] { CardTable.COLUMN_FRONTSIDE, CardTable.COLUMN_BACKSIDE, CardTable.COLUMN_CATEGORY }); // swing widgets private JComboBox m_searchTextBox = new JComboBox(); private RecentItems m_recentSearchTexts = new RecentItems(10, Main.USER_PREFS.node("recent.search.texts")); //$NON-NLS-1$ private JCheckBox m_matchCaseBox = new JCheckBox(Localization.get(LC.MATCH_CASE)); private JRadioButton m_radioBothSides = new JRadioButton(Localization.get(LC.BOTH_SIDES), true); private JRadioButton m_radioFrontSide = new JRadioButton(Localization.get(LC.FRONTSIDE)); private JRadioButton m_radioBackSide = new JRadioButton(Localization.get(LC.FLIPSIDE)); private CategoryComboBox m_categoryBox = new CategoryComboBox(); private StatusBar m_statusBar = new StatusBar(); // these vars are stored when search button is clicked private String m_searchText; private int m_searchSides; private boolean m_matchCase; private Category m_searchCategory; private JPopupMenu m_popupMenu; private static FindFrame m_instance; private class FindAction extends AbstractAction2 { public FindAction() { setName(Localization.get("FindTool.FIND")); //$NON-NLS-1$ } public void actionPerformed(java.awt.event.ActionEvent e) { search(); } } private class CloseAction extends AbstractAction2 { public CloseAction() { setName(Localization.get(LC.CANCEL)); } public void actionPerformed(java.awt.event.ActionEvent e) { close(); } } public static FindFrame getInstance() { if (m_instance == null) { m_instance = new FindFrame(); } return m_instance; } public void show(Category rootCategory, Category selectedCategory) { if (rootCategory != m_categoryBox.getRootCategory()) { clear(); } m_categoryBox.setRootCategory(rootCategory); m_categoryBox.setSelectedCategory(selectedCategory); m_searchTextBox.requestFocus(); setVisible(true); } /** * Remove all search results. */ public void clear() { Category selectedCategory = m_categoryBox.getSelectedCategory(); m_cardTable.getView().setCards(new ArrayList<Card>(0), selectedCategory); } public void search() { String searchText = (String) m_searchTextBox.getSelectedItem(); if (searchText == null || searchText.equals("")) //$NON-NLS-1$ return; m_searchText = searchText; m_recentSearchTexts.push(m_searchText); if (m_radioBothSides.isSelected()) { m_searchSides = SearchTool.BOTH_SIDES; } else { m_searchSides = m_radioFrontSide.isSelected() ? SearchTool.FRONT_SIDE : SearchTool.FLIP_SIDE; } if (m_searchCategory != null) { m_searchCategory.removeObserver(FindFrame.this); } m_searchCategory = m_categoryBox.getSelectedCategory(); m_searchCategory.addObserver(FindFrame.this); m_matchCase = m_matchCaseBox.isSelected(); List<Card> results = SearchTool.search(m_searchText, m_searchSides, m_matchCase, m_searchCategory.getCards()); m_cardTable.getView().setCards(results, m_searchCategory); } public boolean close() { setVisible(false); return true; } /* * @see jmemorize.core.CategoryObserver#onCardEvent */ public void onCardEvent(int type, Card card, Category category, int deck) { // CHECK move into cardtable!? List<Card> cards = m_cardTable.getView().getCards(); // for now we only remove cards but dont add new cards if (type == Events.REMOVED_EVENT) { cards.remove(card); } m_cardTable.getView().setCards(cards, m_searchCategory); updateStatusBar(); } /* * @see jmemorize.core.CategoryObserver#onCategoryEvent */ public void onCategoryEvent(int type, Category category) { // category combo box handles this event by itself } public CardTable getCardTable() { return m_cardTable; } /* * (non-Javadoc) * * @see jmemorize.core.Main.ProgramEndObserver */ public void onProgramEnd() { Settings.storeFrameState(this, FRAME_ID); } private void updateStatusBar() { m_statusBar.setCards(m_cardTable.getView().getCards()); } private JPanel buildSearchPanel() { setupSearchTextBox(); JScrollPane scrollPane = new JScrollPane(m_cardTable); Color color = UIManager.getColor("Table.background"); //$NON-NLS-1$ scrollPane.getViewport().setBackground(color); scrollPane.setPreferredSize(new Dimension(500, 200)); FormLayout layout = new FormLayout("right:pref, 3dlu, pref:grow, 3dlu, pref:grow, 3dlu, pref:grow", // columns //$NON-NLS-1$ // // "p, 3dlu, p, 3dlu, p, 3dlu, p, 9dlu, p, 9dlu, fill:d:grow"); // rows //$NON-NLS-1$ // // CellConstraints cc = new CellConstraints(); DefaultFormBuilder builder = new DefaultFormBuilder(layout); builder.setDefaultDialogBorder(); builder.addLabel(Localization.get("FindTool.SEARCH_TEXT"), cc.xy(1, 1)); //$NON-NLS-1$ builder.add(m_searchTextBox, cc.xyw(3, 1, 5)); builder.addLabel(Localization.get("General.CATEGORY"), cc.xy(1, 3)); //$NON-NLS-1$ builder.add(m_categoryBox, cc.xyw(3, 3, 5)); builder.addLabel(Localization.get("FindTool.SETTINGS"), cc.xy(1, 5)); //$NON-NLS-1$ builder.add(m_radioBothSides, cc.xy(3, 5)); builder.add(m_radioFrontSide, cc.xy(5, 5)); builder.add(m_radioBackSide, cc.xy(7, 5)); builder.add(m_matchCaseBox, cc.xyw(3, 7, 5)); builder.addSeparator(Localization.get("FindTool.RESULTS"), cc.xyw(1, 9, 7)); //$NON-NLS-1$ builder.add(scrollPane, cc.xyw(1, 11, 7)); return builder.getPanel(); } private void setupSearchTextBox() { m_searchTextBox.setEditable(true); m_searchTextBox.setMaximumRowCount(10); m_searchTextBox.addPopupMenuListener(new PopupMenuListener() { public void popupMenuCanceled(PopupMenuEvent arg0) { // ignore } public void popupMenuWillBecomeInvisible(PopupMenuEvent arg0) { // ignore } public void popupMenuWillBecomeVisible(PopupMenuEvent arg0) { m_searchTextBox.setModel(new DefaultComboBoxModel(m_recentSearchTexts.getItems().toArray())); } }); Component comp = m_searchTextBox.getEditor().getEditorComponent(); comp.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent e) { } public void keyReleased(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { search(); } } public void keyTyped(KeyEvent e) { } }); Component editorComp = m_searchTextBox.getEditor().getEditorComponent(); editorComp.addFocusListener(new FocusListener() { public void focusGained(FocusEvent e) { m_searchTextBox.getEditor().selectAll(); } public void focusLost(FocusEvent e) { // ignore } }); m_searchTextBox.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (SwingUtilities.isRightMouseButton(e)) { JComboBox textPane = (JComboBox) e.getSource(); textPane.requestFocus(); m_popupMenu.show(e.getComponent(), e.getX(), e.getY()); } } }); } private JPanel buildSearchBar() { JButton closeButton = new JButton(new CloseAction()); JButton searchButton = new JButton(new FindAction()); JPanel buttonPanel = ButtonBarFactory.buildRightAlignedBar(searchButton, closeButton); buttonPanel.setBorder(new EmptyBorder(0, 5, 5, 10)); getRootPane().setDefaultButton(searchButton); return buttonPanel; } private FindFrame() { m_popupMenu = buildPopupMenu(); initComponents(); Main.getInstance().addProgramEndObserver(this); Settings.loadFrameState(this, FRAME_ID); } private void initComponents() { setTitle(Localization.get("FindTool.FIND")); //$NON-NLS-1$ // build main panel ButtonGroup group = new ButtonGroup(); group.add(m_radioBothSides); group.add(m_radioFrontSide); group.add(m_radioBackSide); JPanel mainPanel = new JPanel(new BorderLayout()); mainPanel.add(buildSearchPanel(), BorderLayout.CENTER); mainPanel.add(buildSearchBar(), BorderLayout.SOUTH); mainPanel.setBorder(new EtchedBorder()); // set status bar m_statusBar = new StatusBar(); m_cardTable.setStatusBar(m_statusBar); getContentPane().add(mainPanel, BorderLayout.CENTER); getContentPane().add(m_statusBar, BorderLayout.SOUTH); setupCardTable(); setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/resource/icons/find.gif"))); //$NON-NLS-1$ pack(); } private void setupCardTable() { // close window on ESC key KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); m_cardTable.getInputMap().put(keyStroke, "Cancel"); //$NON-NLS-1$ m_cardTable.getActionMap().put("Cancel", new AbstractAction() { //$NON-NLS-1$ public void actionPerformed(ActionEvent e) { close(); } }); // overwrite moving to next row when pressing ENTER keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0); m_cardTable.getInputMap().put(keyStroke, "Edit"); //$NON-NLS-1$ m_cardTable.getActionMap().put("Edit", new AbstractAction() { //$NON-NLS-1$ public void actionPerformed(ActionEvent e) { editCards(); } }); m_cardTable.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { if (evt.getClickCount() == 2) { editCards(); } } }); } private void editCards() { Card card = (Card) m_cardTable.getSelectedCards().get(0); List<Card> cards = m_cardTable.getView().getCards(); Category category = m_cardTable.getView().getCategory(); EditCardFrame.getInstance().showCard(card, cards, category, m_searchText, m_searchSides, m_matchCase); } private JPopupMenu buildPopupMenu() { JPopupMenu menu = new JPopupMenu(); menu.add(createMenuItem(new DefaultEditorKit.CopyAction(), Localization.get(LC.COPY), "edit_copy.gif")); menu.add(createMenuItem(new DefaultEditorKit.CutAction(), Localization.get(LC.CUT), "edit_cut.gif")); menu.add(createMenuItem(new DefaultEditorKit.PasteAction(), Localization.get(LC.PASTE), "edit_paste.gif")); return menu; } private JMenuItem createMenuItem(Action action, String text, String icon) { JMenuItem item = new JMenuItem(action); item.setIcon(new ImageIcon(getClass().getResource("/resource/icons/" + icon))); item.setText(text); return item; } }