// This file is part of Penn TotalRecall <http://memory.psych.upenn.edu/TotalRecall>. // // TotalRecall 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, version 3 only. // // TotalRecall 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 TotalRecall. If not, see <http://www.gnu.org/licenses/>. package components.annotations; import info.MyColors; import java.awt.AWTKeyStroke; import java.awt.Component; import java.awt.KeyboardFocusManager; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.util.HashSet; import java.util.Set; import javax.swing.BorderFactory; import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JTable; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.JTableHeader; import behaviors.singleact.JumpToAnnotationAction; /** * <code>JTable</code> that stores the annotations of the open audio file. * * @author Yuvi Masory */ public class AnnotationTable extends JTable implements FocusListener { private static AnnotationTable instance; private static AnnotationTableModel model; private AnnotationTableCellRenderer render; private AnnotationTable() { model = new AnnotationTableModel(); render = new AnnotationTableCellRenderer(); JTableHeader header = getTableHeader(); header.setReorderingAllowed(false); header.setResizingAllowed(true); header.setBorder(BorderFactory.createLineBorder(MyColors.annotationListHeaderBorderColor)); setModel(model); setSelectionMode(ListSelectionModel.SINGLE_SELECTION); addMouseListener(new AnnotationTableMouseAdapter(this)); setDefaultRenderer(Object.class, new DefaultTableCellRenderer(){ @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); return this; } }); addFocusListener(this); getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "jump to annotation"); getActionMap().put("jump to annotation", new JumpToAnnotationAction()); InputMap im = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), "none"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK), "none"); Set<AWTKeyStroke> forwardKeys = new HashSet<AWTKeyStroke>(); forwardKeys.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0, false)); setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, forwardKeys); Set<AWTKeyStroke> backwardKeys = new HashSet<AWTKeyStroke>(); backwardKeys.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK, false)); setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, backwardKeys); getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "none"); getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "none"); getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.SHIFT_DOWN_MASK, false), "none"); getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.SHIFT_DOWN_MASK, false), "none"); } @Override public boolean isFocusable() { return(super.isFocusable() && model.getRowCount() > 0); } @Override public AnnotationTableModel getModel() { return model; } @Override public boolean getScrollableTracksViewportHeight() { Component parent = getParent(); if(parent instanceof javax.swing.JViewport) { return parent.getHeight() > getPreferredSize().height; } return false; } @Override public AnnotationTableCellRenderer getCellRenderer(int row, int col) { return render; } @Override public AnnotationTableCellRenderer getDefaultRenderer(Class<?> columnClass) { return render; } public void focusGained(FocusEvent e) { int anchor = getSelectionModel().getAnchorSelectionIndex(); if(anchor >= 0) { changeSelection(anchor, 0, false, false); changeSelection(anchor, getModel().getColumnCount(), false, true); } else { changeSelection(0, 0, false, false); changeSelection(0, getModel().getColumnCount(), false, true); } } public void focusLost(FocusEvent e) { if(e.isTemporary() == false) { clearSelection(); } } protected static AnnotationTable getInstance() { if(instance == null) { instance = new AnnotationTable(); } return instance; } public static AnnotationTable getFocusTraversalReference() { return getInstance(); } public static Annotation popSelectedAnnotation() { int[] rows = instance.getSelectedRows(); if(rows.length == 1) { return model.getAnnotationAt(rows[0]); } else { return null; } } }