package esmska.gui;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.RowFilter;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.SwingConstants;
import javax.swing.Timer;
import javax.swing.WindowConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableRowSorter;
import esmska.data.Config;
import esmska.data.History;
import esmska.data.Icons;
import esmska.data.event.AbstractDocumentListener;
import esmska.data.event.ValuedEventSupport;
import esmska.data.event.ValuedListener;
import esmska.utils.L10N;
import esmska.utils.RuntimeUtils;
import java.awt.Image;
import java.awt.Toolkit;
import java.util.ResourceBundle;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import org.openide.awt.Mnemonics;
import org.pushingpixels.substance.api.SubstanceLookAndFeel;
import org.pushingpixels.substance.api.renderers.SubstanceDefaultTableCellRenderer;
/** Display all sent messages in a frame
*
* @author ripper
*/
public class HistoryFrame extends javax.swing.JFrame {
public static enum Events {
/** A message is requested to be resent. Event value: History record to resend. */
RESEND_SMS;
}
private static final ResourceBundle l10n = L10N.l10nBundle;
private static final Logger logger = Logger.getLogger(HistoryFrame.class.getName());
private static final Config config = Config.getInstance();
private DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM);
private History history = History.getInstance();
private HistoryTableModel historyTableModel = new HistoryTableModel();
private TableRowSorter<HistoryTableModel> historyTableSorter = new TableRowSorter<HistoryTableModel>(historyTableModel);
private HistoryRowFilter historyTableFilter = new HistoryRowFilter();
private Action deleteAction = new DeleteAction();
private Action resendAction = new ResendAction();
private History.Record selectedHistory;
// <editor-fold defaultstate="collapsed" desc="ValuedEvent support">
private ValuedEventSupport<Events, History.Record> valuedSupport = new ValuedEventSupport<Events, History.Record>(this);
public void addValuedListener(ValuedListener<Events, History.Record> valuedListener) {
valuedSupport.addValuedListener(valuedListener);
}
public void removeValuedListener(ValuedListener<Events, History.Record> valuedListener) {
valuedSupport.removeValuedListener(valuedListener);
}
// </editor-fold>
/** Creates new form HistoryFrame */
public HistoryFrame() {
initComponents();
//set window images
ArrayList<Image> images = new ArrayList<Image>();
images.add(Icons.get("history-16.png").getImage());
images.add(Icons.get("history-32.png").getImage());
images.add(Icons.get("history-48.png").getImage());
setIconImages(images);
//close on Ctrl+W
String command = "close";
getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(
KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), command);
getRootPane().getActionMap().put(command, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
closeButtonActionPerformed(e);
}
});
//if not Substance LaF, add clipboard popup menu to text components
if (!config.getLookAndFeel().equals(ThemeManager.LAF.SUBSTANCE)) {
ClipboardPopupMenu.register(searchField);
ClipboardPopupMenu.register(textArea);
}
//select first row
if (historyTableModel.getRowCount() > 0) {
historyTable.getSelectionModel().setSelectionInterval(0, 0);
}
history.addActionListener(new HistoryActionListener());
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
deleteButton = new JButton();
resendButton = new JButton();
closeButton = new JButton();
searchField = new JTextField();
searchLabel = new JLabel();
clearButton = new JButton();
jSplitPane1 = new JSplitPane();
jScrollPane1 = new JScrollPane();
historyTable = new JTable();
jPanel1 = new JPanel();
jLabel2 = new JLabel();
jLabel1 = new JLabel();
jLabel3 = new JLabel();
jLabel4 = new JLabel();
jLabel5 = new JLabel();
jLabel6 = new JLabel();
dateLabel = new JLabel();
nameLabel = new JLabel();
numberLabel = new JLabel();
gatewayLabel = new JLabel();
senderNumberLabel = new JLabel();
senderNameLabel = new JLabel();
jScrollPane2 = new JScrollPane();
textArea = new JTextArea();
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
setTitle(l10n.getString("HistoryFrame.title")); // NOI18N
addWindowFocusListener(new WindowFocusListener() {
public void windowGainedFocus(WindowEvent evt) {
formWindowGainedFocus(evt);
}
public void windowLostFocus(WindowEvent evt) {
}
});
deleteButton.setAction(deleteAction);
resendButton.setAction(resendAction);
closeButton.setIcon(new ImageIcon(getClass().getResource("/esmska/resources/close-22.png"))); // NOI18N
Mnemonics.setLocalizedText(closeButton, l10n.getString("Close_"));
closeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
closeButtonActionPerformed(evt);
}
});
searchField.setColumns(15);
searchField.setToolTipText(l10n.getString("HistoryFrame.searchField.toolTipText")); // NOI18N
searchField.getDocument().addDocumentListener(new AbstractDocumentListener() {
@Override
public void onUpdate(DocumentEvent e) {
historyTableFilter.requestUpdate();
}
});
//on Mac OS X this will create a native search field with inline icons
searchField.putClientProperty("JTextField.variant", "search");
String command = "clear";
searchField.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), command);
searchField.getActionMap().put(command, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
searchField.setText(null);
}
});
//focus on Ctrl+F
command = "focus search field";
getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
command);
getRootPane().getActionMap().put(command, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
searchField.requestFocusInWindow();
searchFieldFocusGained(null);
}
});
searchField.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent evt) {
searchFieldFocusGained(evt);
}
});
searchField.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
searchFieldKeyPressed(evt);
}
});
searchLabel.setLabelFor(searchField);
Mnemonics.setLocalizedText(searchLabel, l10n.getString("HistoryFrame.searchLabel.text")); // NOI18N
searchLabel.setToolTipText(searchField.getToolTipText());
clearButton.setIcon(new ImageIcon(getClass().getResource("/esmska/resources/clear-22.png"))); // NOI18N
clearButton.setMnemonic('r');
clearButton.setToolTipText(l10n.getString("HistoryFrame.clearButton.toolTipText")); // NOI18N
clearButton.putClientProperty(SubstanceLookAndFeel.FLAT_PROPERTY, Boolean.TRUE);
if (RuntimeUtils.isMac() && config.getLookAndFeel().equals(ThemeManager.LAF.SYSTEM)) {
clearButton.setVisible(false);
}
clearButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
clearButtonActionPerformed(evt);
}
});
jSplitPane1.setOrientation(JSplitPane.VERTICAL_SPLIT);
jSplitPane1.setResizeWeight(1.0);
jSplitPane1.setContinuousLayout(true);
historyTable.setModel(historyTableModel);
historyTable.setDefaultRenderer(Date.class, new TableDateRenderer());
historyTable.getSelectionModel().addListSelectionListener(new HistoryTableListener());
List<RowSorter.SortKey> sortKeys = new ArrayList<RowSorter.SortKey>();
sortKeys.add(new RowSorter.SortKey(0, SortOrder.DESCENDING));
historyTableSorter.setSortKeys(sortKeys);
historyTable.setRowSorter(historyTableSorter);
historyTable.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
historyTableMouseClicked(evt);
}
});
historyTable.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
historyTableKeyPressed(evt);
}
});
jScrollPane1.setViewportView(historyTable);
jSplitPane1.setLeftComponent(jScrollPane1);
Mnemonics.setLocalizedText(jLabel2, l10n.getString("HistoryFrame.jLabel2.text")); // NOI18N
Mnemonics.setLocalizedText(jLabel1, l10n.getString("HistoryFrame.jLabel1.text"));
Mnemonics.setLocalizedText(jLabel3, l10n.getString("HistoryFrame.jLabel3.text"));
Mnemonics.setLocalizedText(jLabel4, l10n.getString("HistoryFrame.jLabel4.text"));
Mnemonics.setLocalizedText(jLabel5, l10n.getString("HistoryFrame.jLabel5.text"));
Mnemonics.setLocalizedText(jLabel6, l10n.getString("HistoryFrame.jLabel6.text"));
Mnemonics.setLocalizedText(dateLabel, " ");
nameLabel.setFont(nameLabel.getFont().deriveFont(nameLabel.getFont().getStyle() | Font.BOLD));
Mnemonics.setLocalizedText(nameLabel, " ");
Mnemonics.setLocalizedText(numberLabel, " ");
Mnemonics.setLocalizedText(gatewayLabel, " ");
Mnemonics.setLocalizedText(senderNumberLabel, " ");
Mnemonics.setLocalizedText(senderNameLabel, " ");
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
jScrollPane2.setViewportView(textArea);
GroupLayout jPanel1Layout = new GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jLabel4)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(gatewayLabel))
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jLabel3)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(dateLabel))
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jLabel2)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(nameLabel))
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jLabel1)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(numberLabel))
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jLabel5)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(senderNumberLabel))
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jLabel6)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(senderNameLabel)))
.addPreferredGap(ComponentPlacement.UNRELATED)
.addComponent(jScrollPane2, GroupLayout.DEFAULT_SIZE, 396, Short.MAX_VALUE))
);
jPanel1Layout.linkSize(SwingConstants.HORIZONTAL, new Component[] {jLabel1, jLabel2, jLabel3, jLabel4, jLabel5, jLabel6});
jPanel1Layout.linkSize(SwingConstants.HORIZONTAL, new Component[] {dateLabel, gatewayLabel, nameLabel, numberLabel, senderNameLabel, senderNumberLabel});
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(Alignment.BASELINE)
.addComponent(jLabel3)
.addComponent(dateLabel))
.addPreferredGap(ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(Alignment.BASELINE)
.addComponent(jLabel2)
.addComponent(nameLabel))
.addPreferredGap(ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(numberLabel))
.addPreferredGap(ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(Alignment.BASELINE)
.addComponent(jLabel4)
.addComponent(gatewayLabel))
.addPreferredGap(ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(Alignment.BASELINE)
.addComponent(jLabel5)
.addComponent(senderNumberLabel))
.addPreferredGap(ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(Alignment.BASELINE)
.addComponent(jLabel6)
.addComponent(senderNameLabel)))
.addComponent(jScrollPane2, GroupLayout.DEFAULT_SIZE, 120, Short.MAX_VALUE)
);
jSplitPane1.setRightComponent(jPanel1);
GroupLayout layout = new GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(Alignment.LEADING)
.addGroup(Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(jSplitPane1, GroupLayout.DEFAULT_SIZE, 533, Short.MAX_VALUE)
.addPreferredGap(ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(Alignment.TRAILING)
.addComponent(closeButton)
.addComponent(resendButton)
.addComponent(deleteButton)))
.addGroup(layout.createSequentialGroup()
.addComponent(searchLabel)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(searchField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(clearButton)))
.addContainerGap())
);
layout.linkSize(SwingConstants.HORIZONTAL, new Component[] {closeButton, deleteButton, resendButton});
layout.setVerticalGroup(
layout.createParallelGroup(Alignment.LEADING)
.addGroup(Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(Alignment.TRAILING)
.addGroup(layout.createParallelGroup(Alignment.BASELINE)
.addComponent(searchField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(searchLabel))
.addComponent(clearButton))
.addPreferredGap(ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(resendButton)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(deleteButton)
.addPreferredGap(ComponentPlacement.RELATED, 336, Short.MAX_VALUE)
.addComponent(closeButton))
.addComponent(jSplitPane1, GroupLayout.DEFAULT_SIZE, 444, Short.MAX_VALUE))
.addContainerGap())
);
layout.linkSize(SwingConstants.VERTICAL, new Component[] {closeButton, deleteButton, resendButton});
pack();
}// </editor-fold>//GEN-END:initComponents
private void closeButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
this.setVisible(false);
this.dispose();
}//GEN-LAST:event_closeButtonActionPerformed
private void historyTableMouseClicked(MouseEvent evt) {//GEN-FIRST:event_historyTableMouseClicked
//only on left double click
if (SwingUtilities.isLeftMouseButton(evt) && evt.getClickCount() >= 2) {
resendButton.doClick(0);
}
}//GEN-LAST:event_historyTableMouseClicked
private void historyTableKeyPressed(KeyEvent evt) {//GEN-FIRST:event_historyTableKeyPressed
switch (evt.getKeyCode()) {
case KeyEvent.VK_ENTER:
evt.consume();
resendButton.doClick(0);
break;
case KeyEvent.VK_DELETE:
deleteButton.doClick(0);
break;
}
}//GEN-LAST:event_historyTableKeyPressed
private void clearButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_clearButtonActionPerformed
searchField.setText(null);
searchField.requestFocusInWindow();
}//GEN-LAST:event_clearButtonActionPerformed
private void searchFieldFocusGained(FocusEvent evt) {//GEN-FIRST:event_searchFieldFocusGained
searchField.selectAll();
}//GEN-LAST:event_searchFieldFocusGained
private void searchFieldKeyPressed(KeyEvent evt) {//GEN-FIRST:event_searchFieldKeyPressed
if (evt.getKeyCode() == KeyEvent.VK_DOWN ||
evt.getKeyCode() == KeyEvent.VK_UP) {
//redirect the event to the history table
historyTable.requestFocusInWindow();
historyTable.dispatchEvent(evt);
}
}//GEN-LAST:event_searchFieldKeyPressed
private void formWindowGainedFocus(WindowEvent evt) {//GEN-FIRST:event_formWindowGainedFocus
historyTable.requestFocusInWindow();
}//GEN-LAST:event_formWindowGainedFocus
/** Delete sms from history */
private class DeleteAction extends AbstractAction {
private final String deleteOption = l10n.getString("Delete");
private final String cancelOption = l10n.getString("Cancel");
private final Object[] options = RuntimeUtils.sortDialogOptions(
cancelOption, deleteOption);
private final String message = l10n.getString("HistoryFrame.remove_selected");
public DeleteAction() {
L10N.setLocalizedText(this, l10n.getString("Delete_"));
putValue(LARGE_ICON_KEY, Icons.get("delete-22.png"));
putValue(SHORT_DESCRIPTION, l10n.getString("Delete_selected_messages_from_history"));
this.setEnabled(false);
}
@Override
public void actionPerformed(ActionEvent e) {
historyTable.requestFocusInWindow(); //always transfer focus
int[] rows = historyTable.getSelectedRows();
if (rows.length <= 0) {
return;
}
ArrayList<History.Record> histToDelete = new ArrayList<History.Record>();
for (int i : rows) {
i = historyTable.getRowSorter().convertRowIndexToModel(i);
histToDelete.add(history.getRecord(i));
}
//show dialog
JOptionPane pane = new JOptionPane(message, JOptionPane.WARNING_MESSAGE,
JOptionPane.DEFAULT_OPTION, null, options, deleteOption);
JDialog dialog = pane.createDialog(HistoryFrame.this, null);
dialog.setResizable(true);
RuntimeUtils.setDocumentModalDialog(dialog);
dialog.pack();
dialog.setVisible(true);
//return if should not delete
if (!deleteOption.equals(pane.getValue())) {
return;
}
//confirmed, let's delete it
history.removeRecords(histToDelete);
//refresh table
historyTableModel.fireTableDataChanged();
historyTable.getSelectionModel().clearSelection();
}
}
/** Resend chosen sms from history */
private class ResendAction extends AbstractAction {
public ResendAction() {
L10N.setLocalizedText(this, l10n.getString("Forward_"));
putValue(LARGE_ICON_KEY, Icons.get("send-22.png"));
putValue(SHORT_DESCRIPTION, l10n.getString("HistoryFrame.resend_message"));
this.setEnabled(false);
}
@Override
public void actionPerformed(ActionEvent e) {
if (selectedHistory == null) {
return;
}
logger.fine("Forwarding message from history: " + selectedHistory);
//fire event and close
valuedSupport.fireEventOccured(Events.RESEND_SMS, selectedHistory);
closeButton.doClick(0);
}
}
/** Listener for history changes */
private class HistoryActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
historyTableModel.fireTableDataChanged();
historyTable.getSelectionModel().clearSelection();
}
}
/** Table model for showing sms history */
private class HistoryTableModel extends AbstractTableModel {
@Override
public int getRowCount() {
return history.getRecords().size();
}
@Override
public int getColumnCount() {
return 3;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
History.Record record = history.getRecord(rowIndex);
switch (columnIndex) {
case 0:
return record.getDate();
case 1:
String name = record.getName();
return name != null && !name.equals("") ? name : record.getNumber();
case 2:
return record.getText().replaceAll("\n+", " "); //show spaces instead of linebreaks
default:
logger.warning("Index out of bounds!");
return null;
}
}
@Override
public String getColumnName(int column) {
switch (column) {
case 0:
return l10n.getString("Date");
case 1:
return l10n.getString("Recipient");
case 2:
return l10n.getString("Text");
default:
logger.warning("Index out of bounds!");
return null;
}
}
@Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return Date.class;
case 1:
case 2:
return String.class;
default:
logger.warning("Index out of bounds!");
return Object.class;
}
}
}
/** Listener for changes in history table */
private class HistoryTableListener implements ListSelectionListener {
@Override
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting()) {
return;
}
int index = historyTable.getSelectedRow();
boolean selected = (index >= 0);
deleteAction.setEnabled(selected);
resendAction.setEnabled(selected);
History.Record record = null;
if (selected) {
index = historyTable.getRowSorter().convertRowIndexToModel(index);
record = history.getRecord(index);
}
dateLabel.setText(selected ? df.format(record.getDate()) : null);
nameLabel.setText(selected ? record.getName() : null);
numberLabel.setText(selected ? record.getNumber() : null);
gatewayLabel.setText(selected ? record.getGateway() : null);
senderNameLabel.setText(selected ? record.getSenderName() : null);
senderNumberLabel.setText(selected ? record.getSenderNumber() : null);
textArea.setText(selected ? record.getText() : null);
textArea.setCaretPosition(0);
selectedHistory = record;
}
}
/** Renderer for date columns in history table */
private class TableDateRenderer extends SubstanceDefaultTableCellRenderer {
private final ImageIcon icon = Icons.get("message-16.png");
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component comp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
JLabel label = (JLabel) comp;
label.setText(df.format(value));
label.setIcon(icon);
return label;
}
}
/** Filter for searching in history table */
private class HistoryRowFilter extends RowFilter<HistoryTableModel, Integer> {
private Timer timer = new Timer(500, new ActionListener() { //updating after each event is slow,
@Override
public void actionPerformed(ActionEvent e) { //therefore there is timer
historyTableSorter.setRowFilter(HistoryRowFilter.this);
if (historyTable.getRowCount() > 0) {
historyTable.changeSelection(0, 0, false, false);
historyTable.scrollRectToVisible(historyTable.getCellRect(0, 0, true));
}
}
});
public HistoryRowFilter() {
timer.setRepeats(false);
}
@Override
public boolean include(Entry<? extends HistoryTableModel, ? extends Integer> entry) {
History.Record record = history.getRecord(entry.getIdentifier());
String pattern = searchField.getText().toLowerCase();
//search through text, name, number and date
if (record.getText() != null && record.getText().toLowerCase().contains(pattern)) {
return true;
}
if (record.getNumber() != null && record.getNumber().toLowerCase().contains(pattern)) {
return true;
}
if (record.getName() != null && record.getName().toLowerCase().contains(pattern)) {
return true;
}
if (record.getDate() != null && df.format(record.getDate()).toLowerCase().contains(pattern)) {
return true;
}
return false;
}
/** request history search filter to be updated */
public void requestUpdate() {
timer.restart();
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private JButton clearButton;
private JButton closeButton;
private JLabel dateLabel;
private JButton deleteButton;
private JLabel gatewayLabel;
private JTable historyTable;
private JLabel jLabel1;
private JLabel jLabel2;
private JLabel jLabel3;
private JLabel jLabel4;
private JLabel jLabel5;
private JLabel jLabel6;
private JPanel jPanel1;
private JScrollPane jScrollPane1;
private JScrollPane jScrollPane2;
private JSplitPane jSplitPane1;
private JLabel nameLabel;
private JLabel numberLabel;
private JButton resendButton;
private JTextField searchField;
private JLabel searchLabel;
private JLabel senderNameLabel;
private JLabel senderNumberLabel;
private JTextArea textArea;
// End of variables declaration//GEN-END:variables
}