package gsingh.learnkirtan.ui.shabadeditor.tableeditor; import gsingh.learnkirtan.Keys; import gsingh.learnkirtan.ui.WindowTitleManager; import gsingh.learnkirtan.ui.action.ActionFactory; import gsingh.learnkirtan.validation.Validator; import java.awt.Color; import java.awt.Component; import java.awt.Font; import java.awt.Point; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.util.EventObject; import java.util.HashSet; import java.util.Set; import java.util.StringTokenizer; import javax.swing.AbstractAction; import javax.swing.JOptionPane; import javax.swing.JTable; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.text.JTextComponent; @SuppressWarnings("serial") public class ShabadTable extends JTable { private Set<Point> invalidCells = new HashSet<Point>(); private static final Font font = new Font("Arial", Font.PLAIN, 20); private boolean isSelectAllForMouseEvent = false; private boolean isSelectAllForActionEvent = false; private boolean isSelectAllForKeyEvent = false; public ShabadTable(int rows, int cols, WindowTitleManager titleManager, ActionFactory actionFactory) { super(new UndoTableModel()); UndoTableModel model = (UndoTableModel) getModel(); model.setRowCount(rows); model.setColumnCount(cols); Integer[] headers = new Integer[cols]; for (int i = 0; i < 16; i++) { headers[i] = i + 1; } setSelectAllForEdit(true); setCellSelectionEnabled(true); setRowHeight(20); setFont(new Font("Arial", Font.PLAIN, 20)); model.setColumnIdentifiers(headers); getTableHeader().setReorderingAllowed(false); DefaultTableCellRenderer renderer = new DefaultTableCellRenderer(); renderer.setHorizontalAlignment(SwingConstants.CENTER); for (int i = 0; i < 16; i++) { TableColumn column = getColumnModel().getColumn(i); column.setCellRenderer(renderer); } setActions(actionFactory); } private void setActions(ActionFactory actionFactory) { getInputMap().put(Keys.UNDO_KEY, "undo"); getInputMap().put(Keys.REDO_KEY, "redo"); getInputMap().put(Keys.SAVE_KEY, "save"); getInputMap().put(Keys.OPEN_KEY, "open"); getInputMap().put(Keys.NEW_KEY, "create"); getInputMap().put(Keys.CUT_KEY, "cut"); getInputMap().put(Keys.COPY_KEY, "copy"); getInputMap().put(Keys.PASTE_KEY, "paste"); getInputMap().put(Keys.DELETE_KEY, "delete"); getActionMap().put("save", actionFactory.newSaveAction()); getActionMap().put("open", actionFactory.newOpenAction()); getActionMap().put("create", actionFactory.newCreateAction()); getActionMap().put("cut", new CutAction()); getActionMap().put("copy", new CopyAction()); getActionMap().put("paste", new PasteAction()); getActionMap().put("delete", new DeleteAction()); } /* * Override to provide Select All editing functionality */ @Override public boolean editCellAt(int row, int column, EventObject e) { boolean result = super.editCellAt(row, column, e); if (isSelectAllForMouseEvent || isSelectAllForActionEvent || isSelectAllForKeyEvent) { selectAll(e); } return result; } /* * Select the text when editing on a text related cell is started */ private void selectAll(EventObject e) { final Component editor = getEditorComponent(); if (editor == null || !(editor instanceof JTextComponent)) return; if (e == null) { ((JTextComponent) editor).selectAll(); return; } // Typing in the cell was used to activate the editor if (e instanceof KeyEvent && isSelectAllForKeyEvent) { ((JTextComponent) editor).selectAll(); return; } // F2 was used to activate the editor if (e instanceof ActionEvent && isSelectAllForActionEvent) { ((JTextComponent) editor).selectAll(); return; } // A mouse click was used to activate the editor. // Generally this is a double click and the second mouse click is // passed to the editor which would remove the text selection unless // we use the invokeLater() if (e instanceof MouseEvent && isSelectAllForMouseEvent) { SwingUtilities.invokeLater(new Runnable() { public void run() { ((JTextComponent) editor).selectAll(); } }); } } // // Newly added methods // /* * Sets the Select All property for for all event types */ public void setSelectAllForEdit(boolean isSelectAllForEdit) { setSelectAllForMouseEvent(isSelectAllForEdit); setSelectAllForActionEvent(isSelectAllForEdit); setSelectAllForKeyEvent(isSelectAllForEdit); } /* * Set the Select All property when editing is invoked by the mouse */ public void setSelectAllForMouseEvent(boolean isSelectAllForMouseEvent) { this.isSelectAllForMouseEvent = isSelectAllForMouseEvent; } /* * Set the Select All property when editing is invoked by the "F2" key */ public void setSelectAllForActionEvent(boolean isSelectAllForActionEvent) { this.isSelectAllForActionEvent = isSelectAllForActionEvent; } /* * Set the Select All property when editing is invoked by typing directly * into the cell */ public void setSelectAllForKeyEvent(boolean isSelectAllForKeyEvent) { this.isSelectAllForKeyEvent = isSelectAllForKeyEvent; } @Override public Component prepareRenderer(TableCellRenderer renderer, int row, int col) { Component c = super.prepareRenderer(renderer, row, col); if (!c.getBackground().equals(getSelectionBackground())) { if (row % 2 == 1) { if (isEnabled()) { c.setBackground(Color.LIGHT_GRAY); } else { c.setBackground(Color.LIGHT_GRAY); } } else { if (isEnabled()) { c.setBackground(Color.WHITE); } else { c.setBackground(new Color(0xE5, 0xE5, 0xE5)); } } } if (row % 2 == 1) { String value = (String) getValueAt(row, col); Point point = new Point(row, col); if (value != null && !value.equals("") && !Validator.validate(value)) { if (!c.getBackground().equals(getSelectionBackground())) { c.setBackground(new Color(0xFF, 0x30, 0x30)); // Red } else { c.setBackground(new Color(0xFF, 0x70, 0x70)); // Light // Red } invalidCells.add(point); } else { if (invalidCells.contains(point)) { invalidCells.remove(point); } } } return c; } @Override public Component prepareEditor(TableCellEditor editor, int row, int col) { Component c = super.prepareEditor(editor, row, col); c.setFont(font); return c; } public boolean isValidShabad() { return invalidCells.isEmpty(); } public class CutAction extends AbstractAction { private CopyAction copyAction = new CopyAction(); @Override public void actionPerformed(ActionEvent e) { JTable jTable = ShabadTable.this; copyAction.actionPerformed(e); if (copyAction.success) { int[] rowsselected = jTable.getSelectedRows(); int[] colsselected = jTable.getSelectedColumns(); for (int row : rowsselected) { for (int col : colsselected) { jTable.setValueAt("", row, col); } } } } } public class DeleteAction extends AbstractAction { @Override public void actionPerformed(ActionEvent e) { JTable jTable = ShabadTable.this; int[] rowsselected = jTable.getSelectedRows(); int[] colsselected = jTable.getSelectedColumns(); for (int row : rowsselected) { for (int col : colsselected) { jTable.setValueAt("", row, col); } } } } /** * @see "http://www.javaworld.com/javatips/jw-javatip77.html" */ public class CopyAction extends AbstractAction { public boolean success = false; @Override public void actionPerformed(ActionEvent e) { JTable jTable = ShabadTable.this; StringBuffer sbf = new StringBuffer(); // Check to ensure we have selected only a contiguous block of cells int numcols = jTable.getSelectedColumnCount(); int numrows = jTable.getSelectedRowCount(); int[] rowsselected = jTable.getSelectedRows(); int[] colsselected = jTable.getSelectedColumns(); if (!((numrows - 1 == rowsselected[rowsselected.length - 1] - rowsselected[0] && numrows == rowsselected.length) && (numcols - 1 == colsselected[colsselected.length - 1] - colsselected[0] && numcols == colsselected.length))) { JOptionPane.showMessageDialog(null, "Invalid Copy Selection", "Invalid Copy Selection", JOptionPane.ERROR_MESSAGE); success = false; return; } for (int i = 0; i < numrows; i++) { for (int j = 0; j < numcols; j++) { sbf.append(jTable.getValueAt(rowsselected[i], colsselected[j])); if (j < numcols - 1) sbf.append("\t"); } sbf.append("\n"); } StringSelection stsel = new StringSelection(sbf.toString()); Clipboard system = Toolkit.getDefaultToolkit().getSystemClipboard(); system.setContents(stsel, stsel); success = true; } } public class PasteAction extends AbstractAction { @Override public void actionPerformed(ActionEvent e) { JTable jTable = ShabadTable.this; Clipboard system = Toolkit.getDefaultToolkit().getSystemClipboard(); int startRow = (jTable.getSelectedRows())[0]; int startCol = (jTable.getSelectedColumns())[0]; try { Transferable t = system.getContents(this); if (t.isDataFlavorSupported(DataFlavor.stringFlavor)) { String trstring = (String) t .getTransferData(DataFlavor.stringFlavor); StringTokenizer st1 = new StringTokenizer(trstring, "\n"); for (int i = 0; st1.hasMoreTokens(); i++) { String rowstring = st1.nextToken(); StringTokenizer st2 = new StringTokenizer(rowstring, "\t "); for (int j = 0; st2.hasMoreTokens(); j++) { String value = st2.nextToken(); if (!value.equals("null")) { if (startRow + i < jTable.getRowCount() && startCol + j < jTable .getColumnCount()) jTable.setValueAt(value, startRow + i, startCol + j); } } } } } catch (Exception ex) { ex.printStackTrace(); } } } }