/* * Copyright 2000-2010 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.ui; import com.intellij.util.PairFunction; import com.intellij.util.containers.Convertor; import javax.swing.*; import javax.swing.table.TableModel; import java.util.ListIterator; public class TableSpeedSearch extends SpeedSearchBase { private static final PairFunction TO_STRING = new PairFunction() { @Override public String fun(Object o, Cell cell) { return o == null || o instanceof Boolean ? "" : o.toString(); } }; private final PairFunction myToStringConvertor; public TableSpeedSearch(JTable table) { this(table, TO_STRING); } public TableSpeedSearch(JTable table, final Convertor toStringConvertor) { this(table, new PairFunction() { @Override public String fun(Object o, Cell c) { return toStringConvertor.convert(o); } }); } public TableSpeedSearch(JTable table, final PairFunction toStringConvertor) { super(table); myToStringConvertor = toStringConvertor; // edit on F2 & double click, do not interfere with quick search table.putClientProperty("JTable.autoStartsEdit", Boolean.FALSE); } @Override protected boolean isSpeedSearchEnabled() { JTable table = getComponent(); boolean tableIsNotEmpty = table.getRowCount() != 0 && table.getColumnCount() != 0; return tableIsNotEmpty && !table.isEditing() && super.isSpeedSearchEnabled(); } @Override protected ListIterator getElementIterator(int startingIndex) { return new MyListIterator(startingIndex); } @Override protected int getElementCount() { final TableModel tableModel = myComponent.getModel(); return tableModel.getRowCount() * tableModel.getColumnCount(); } @Override protected void selectElement(Object element, String selectedText) { final int index = ((Integer)element).intValue(); final TableModel model = myComponent.getModel(); final int row = index / model.getColumnCount(); final int col = index % model.getColumnCount(); myComponent.getSelectionModel().setSelectionInterval(row, row); myComponent.getColumnModel().getSelectionModel().setSelectionInterval(col, col); TableUtil.scrollSelectionToVisible(myComponent); } @Override protected int getSelectedIndex() { final int row = myComponent.getSelectedRow(); final int col = myComponent.getSelectedColumn(); // selected row is not enough as we want to select specific cell in a large multi-column table return row > -1 && col > -1 ? row * myComponent.getModel().getColumnCount() + col : -1; } @Override protected Object[] getAllElements() { throw new UnsupportedOperationException("Not implemented"); } @Override protected String getElementText(Object element) { final int index = ((Integer)element).intValue(); final TableModel model = myComponent.getModel(); int row = myComponent.convertRowIndexToModel(index / model.getColumnCount()); int col = myComponent.convertColumnIndexToModel(index % model.getColumnCount()); Object value = model.getValueAt(row, col); return myToStringConvertor.fun(value, new Cell(row, col)); } private class MyListIterator implements ListIterator { private int myCursor; public MyListIterator(int startingIndex) { final int total = getElementCount(); myCursor = startingIndex < 0 ? total : startingIndex; } @Override public boolean hasNext() { return myCursor < getElementCount(); } @Override public Object next() { return myCursor++; } @Override public boolean hasPrevious() { return myCursor > 0; } @Override public Object previous() { return (myCursor--) - 1; } @Override public int nextIndex() { return myCursor; } @Override public int previousIndex() { return myCursor - 1; } @Override public void remove() { throw new AssertionError("Not Implemented"); } @Override public void set(Object o) { throw new AssertionError("Not Implemented"); } @Override public void add(Object o) { throw new AssertionError("Not Implemented"); } } }