/* * To change this template, choose Tools | Templates * and open the template in the editor. */ /* * GridSearchView.java * * Created on 17.12.2009, 16:05:50 */ package com.eas.client.forms.components.model.grid; import com.bearsoft.gui.grid.data.CellData; import com.bearsoft.gui.grid.rendering.InsettedRenderer; import com.bearsoft.gui.grid.rows.TabularRowsSorter; import com.eas.client.forms.Forms; import java.awt.Component; import java.awt.Rectangle; import java.awt.Window; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; /** * * @author mg */ public class GridSearchView extends javax.swing.JPanel implements ListSelectionListener { protected ModelGrid grid; protected FindAction findAction = new FindAction(); protected CloseAction closeAction = new CloseAction(); protected SearchEntry cell2LookAt = new SearchEntry(); protected SearchEntry lastFound = new SearchEntry(); protected boolean caseSensitive = false; protected boolean wholeMatch = false; @Override public void valueChanged(ListSelectionEvent e) { cell2LookAt = null; } private String convertValue2StringWithRenderer(Object oValue, int col) { if (oValue != null) { TableColumnModel columnModel = grid.getColumnModel(); String sValue = null; TableColumn tCol = columnModel.getColumn(col); if (tCol instanceof TableColumn) { TableColumn gCol = (TableColumn) tCol; TableCellRenderer renderer = gCol.getCellRenderer(); if (renderer != null) { if (renderer instanceof InsettedRenderer) { renderer = ((InsettedRenderer) renderer).unwrap(); } Component rComp = renderer.getTableCellRendererComponent(grid.getBottomRightTable(), oValue, false, false, 0, 0); if (rComp instanceof JLabel) { sValue = ((JLabel) rComp).getText(); } } } if (sValue == null) { if (oValue instanceof CellData) { CellData cd = (CellData) oValue; oValue = cd.display != null ? cd.display : cd.data; if (oValue != null) { sValue = oValue.toString(); } else { sValue = ""; } } else { sValue = oValue.toString(); } } return sValue; } else { return null; } } protected class SearchEntry { public int row = 0; public int column = 0; } private void makeVisible() { // achive models needed TableColumnModel columnModel = grid.getColumnModel(); ListSelectionModel rowsSelectionModel = grid.getRowsSelectionModel(); ListSelectionModel columnSelectionModel = columnModel.getSelectionModel(); grid.getRowsSelectionModel().removeListSelectionListener(this); try { // table rowsSelectionModel.setSelectionInterval(lastFound.row, lastFound.row); columnSelectionModel.setSelectionInterval(lastFound.column, lastFound.column); // make needed cell visible JTable cellTable = grid.getTableByViewCell(lastFound.row, lastFound.column); if (cellTable != null) { int cellRow = lastFound.row; if (cellRow >= grid.getTopLeftTable().getRowCount()) { cellRow -= grid.getTopLeftTable().getRowCount(); } int cellCol = lastFound.column; if (cellCol >= grid.getTopLeftTable().getColumnCount()) { cellCol -= grid.getTopLeftTable().getColumnCount(); } Rectangle cellRect = cellTable.getCellRect(cellRow, cellCol, true); assert cellRect != null; cellTable.scrollRectToVisible(cellRect); } } finally { grid.getRowsSelectionModel().addListSelectionListener(this); } } private boolean findNext(String txt2Find) { if (txt2Find != null) { // choose initial parameters int row = cell2LookAt.row; int col = cell2LookAt.column; TabularRowsSorter<? extends TableModel> rowsSorter = grid.getRowSorter(); TableColumnModel columnModel = grid.getColumnModel(); if (rowsSorter.getViewRowCount() <= 0 || columnModel.getColumnCount() <= 0) { return false; } while (true) { TableColumn tCol = columnModel.getColumn(col); Object oValue = rowsSorter.getModel().getValueAt(rowsSorter.convertRowIndexToModel(row), tCol.getModelIndex()); boolean found = false; if (oValue != null) { String sValue = convertValue2StringWithRenderer(oValue, col); if (!caseSensitive) { txt2Find = txt2Find.toLowerCase(); sValue = sValue.toLowerCase(); } sValue = sValue.replaceAll("[^а-я-А-Я\\w\\s\\p{Punct}]+", " "); txt2Find = txt2Find.replaceAll("[^а-я-А-Я\\w\\s\\p{Punct}]+", " "); if (wholeMatch) { found = txt2Find.equals(sValue); } else { found = !sValue.isEmpty() && (sValue.contains(txt2Find) || txt2Find.contains(sValue)); } } // mark the founded value place if (found) { lastFound.column = col; lastFound.row = row; } // find next cell to look at row++; if (row >= rowsSorter.getViewRowCount()) { row = 0; col++; if (col >= columnModel.getColumnCount()) { // model ended cell2LookAt.column = 0; cell2LookAt.row = 0; if (!found) { return false; } } } if (found) { if (col >= columnModel.getColumnCount()) { cell2LookAt.column = 0; } else { cell2LookAt.column = col; } cell2LookAt.row = row; return true; } } } return false; } private void checkActions() { findAction.checkEnabled(); closeAction.checkEnabled(); } protected class SurrogateFindAction extends AbstractAction { @Override public void actionPerformed(ActionEvent e) { findAction.actionPerformed(e); } } protected class FindAction extends AbstractAction { public FindAction() { super(); putValue(Action.NAME, Forms.getLocalizedString("btnFind")); setEnabled(false); } public void checkEnabled() { setEnabled(isEnabled()); } @Override public boolean isEnabled() { return txtText2Find.getText() != null && !txtText2Find.getText().isEmpty(); } @Override public void actionPerformed(ActionEvent e) { if (isEnabled()) { if (cell2LookAt == null) { cell2LookAt = new SearchEntry(); cell2LookAt.column = grid.getColumnModel().getSelectionModel().getLeadSelectionIndex(); cell2LookAt.row = grid.getRowsSelectionModel().getLeadSelectionIndex(); if (cell2LookAt.column == -1 || cell2LookAt.row == -1) { cell2LookAt.column = 0; cell2LookAt.row = 0; } else { // find next cell to look at to avoid search to stop at position just selected cell2LookAt.row++; if (cell2LookAt.row >= grid.getRowSorter().getViewRowCount()) { cell2LookAt.row = 0; cell2LookAt.column++; if (cell2LookAt.column >= grid.getColumnModel().getColumnCount()) { // model has ended cell2LookAt.column = 0; cell2LookAt.row = 0; } } } } if (findNext(txtText2Find.getText())) { makeVisible(); } else { JOptionPane.showMessageDialog(GridSearchView.this, Forms.getLocalizedString("notFound"), Forms.getLocalizedString("Search"), JOptionPane.INFORMATION_MESSAGE); } } } } protected class CloseAction extends AbstractAction { public CloseAction() { super(); putValue(Action.NAME, Forms.getLocalizedString("btnClose")); } public void checkEnabled() { setEnabled(isEnabled()); } @Override public void actionPerformed(ActionEvent e) { Window w = SwingUtilities.getWindowAncestor(GridSearchView.this); if (w != null) { w.setVisible(false); w.dispose(); } } } protected class SearchViewDocumentListener implements DocumentListener { @Override public void insertUpdate(DocumentEvent e) { checkActions(); } @Override public void removeUpdate(DocumentEvent e) { checkActions(); } @Override public void changedUpdate(DocumentEvent e) { checkActions(); } } /** * Creates new form GridSearchView */ public GridSearchView(ModelGrid aGrid) { initComponents(); grid = aGrid; //grid.getRowsSelectionModel().addListSelectionListener(this); btnClose.setAction(closeAction); btnFind.setAction(findAction); txtText2Find.setAction(new SurrogateFindAction()); txtText2Find.getDocument().addDocumentListener(new SearchViewDocumentListener()); } /** * 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. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { btnFind = new javax.swing.JButton(); btnClose = new javax.swing.JButton(); lblFind = new javax.swing.JLabel(); txtText2Find = new javax.swing.JTextField(); chkCase = new javax.swing.JCheckBox(); chkWhole = new javax.swing.JCheckBox(); setMinimumSize(new java.awt.Dimension(330, 100)); btnFind.setText(Forms.getLocalizedString("btnFind")); // NOI18N btnFind.setMargin(new java.awt.Insets(2, 2, 2, 2)); btnClose.setText(Forms.getLocalizedString("btnClose")); // NOI18N btnClose.setMargin(new java.awt.Insets(2, 2, 2, 2)); lblFind.setText(Forms.getLocalizedString("lblFind")); // NOI18N chkCase.setText(Forms.getLocalizedString("chkCase")); // NOI18N chkCase.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { chkCaseActionPerformed(evt); } }); chkWhole.setText(Forms.getLocalizedString("chkWhole")); // NOI18N chkWhole.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { chkWholeActionPerformed(evt); } }); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addComponent(lblFind) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(txtText2Find, javax.swing.GroupLayout.DEFAULT_SIZE, 304, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addComponent(chkCase) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(btnFind, javax.swing.GroupLayout.DEFAULT_SIZE, 105, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(btnClose, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(chkWhole)))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(lblFind) .addComponent(txtText2Find, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(chkCase) .addComponent(chkWhole)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(btnClose) .addComponent(btnFind, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGap(9, 9, 9)) ); }// </editor-fold>//GEN-END:initComponents private void chkCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkCaseActionPerformed caseSensitive = chkCase.isSelected(); }//GEN-LAST:event_chkCaseActionPerformed private void chkWholeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkWholeActionPerformed wholeMatch = chkWhole.isSelected(); }//GEN-LAST:event_chkWholeActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton btnClose; private javax.swing.JButton btnFind; private javax.swing.JCheckBox chkCase; private javax.swing.JCheckBox chkWhole; private javax.swing.JLabel lblFind; private javax.swing.JTextField txtText2Find; // End of variables declaration//GEN-END:variables }