Процесс обработки клавиатурного сочетания следующий:
- в методе компонента processKeyBinding сохраним нажатую комбинацию.
- далее в методе компонента changeSelection обрабатываем комбинацию (подсмотренно у JIDE).
Для примера реализуем аналог NavigatableTable из JIDE. Пишем модель навигации:
public interface NavigatableModel {
boolean isNavigableAt(int rowIndex, int columnIndex);
boolean isNavigationOn();
}
Реализуем эту модель в нашей модели таблицы:
public class NavigationTableModel extends DefautTableModel implements NavigatableModel {
@Override
public int getColumnCount() {
return 10;
}
@Override
public int getRowCount() {
return 10;
}
@Override
public Object getValueAt(int row, int column) {
return row*column;
}
@Override
public boolean isCellEditable(int row, int column) {
return true;
}
public boolean isNavigableAt(int rowIndex, int columnIndex) {
return rowIndex % 2 == columnIndex % 2;
}
public boolean isNavigationOn() {
return true;
}
}
@Override
public int getColumnCount() {
return 10;
}
@Override
public int getRowCount() {
return 10;
}
@Override
public Object getValueAt(int row, int column) {
return row*column;
}
@Override
public boolean isCellEditable(int row, int column) {
return true;
}
public boolean isNavigableAt(int rowIndex, int columnIndex) {
return rowIndex % 2 == columnIndex % 2;
}
public boolean isNavigationOn() {
return true;
}
}
UI-делегат для таблицы:
public class BasicNavigatableTableUI extends BasicTableUI {
public static ComponentUI createUI(JComponent jcomponent) {
return new BasicNavigatableTableUI();
}
@Override
public void installUI(JComponent c) {
super.installUI(c);
c.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), "scrolRightChangeSelection");
c.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK), "scrolLeftChangeSelection");
c.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "scrolDownChangeSelection");
c.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_DOWN_MASK), "scrolUpChangeSelection");
}
}
В делегате добавляются идентификаторы действий:
- TAB - перейти к следующей доступной ячейке в ряду
- Shift+TAB - перейти к предыдущей доступной ячейке в ряду
- ENTER - перейти к следующей доступной ячейке в колонке
- Shift+ENTER - перейти к предыдущей доступной ячейке в колонке
public class NavigatableTable extends JTable {
public boolean isCellNavigatable(int row, int column) {
TableModel tableModel = getModel();
if (!(tableModel instanceof NavigatableModel)) {
return true;
}
NavigatableModel navigatableModel = (NavigatableModel) tableModel;
if (!navigatableModel.isNavigationOn()) {
return true;
}
return navigatableModel.isNavigableAt(row, column);
}
@Override
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
keyStroke = ks;
return super.processKeyBinding(ks, e, condition, pressed);
}
@Override
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
TableModel tableModel = getModel();
if (!(tableModel instanceof NavigatableModel)) {
super.changeSelection(rowIndex, columnIndex, toggle, extend);
return;
}
NavigatableModel navigatableModel = (NavigatableModel) tableModel;
if (!navigatableModel.isNavigationOn()) {
super.changeSelection(rowIndex, columnIndex, toggle, extend);
return;
}
scrollRectToVisible(getCellRect(rowIndex, columnIndex, true));
int row = getSelectedRow();
int column = getSelectedColumn();
final Object o = getInputMap().get(keyStroke);
if (o==null) {
super.changeSelection(rowIndex, columnIndex, toggle, extend);
return;
}
if (o.equals("scrolRightChangeSelection")) {
boolean found = false;
int i = column + 1;
int j = row;
while (!found) {
while (i
if (isCellNavigatable(j, i)) {
found = true;
break;
}
i++;
}
if (!found) {
i = 0;
j++;
if (j>=getRowCount()) {
j=0;
}
}
if (j==row && i==column) { //full table scan complete
break;
}
}
column = i;
row = j;
}
else if (o.equals("scrolLeftChangeSelection")) {
boolean found = false;
int i = column - 1;
int j = row;
if (i<0) {
i = getColumnCount()-1;
j--;
}
if (j<0) {
j=getRowCount()-1;
}
while (!found) {
if (j==row && i==column) { //full table scan complete
break;
}
while (i>=0) {
if (isCellNavigatable(j, i)) {
found = true;
break;
}
i--;
}
if (!found) {
i = getColumnCount()-1;
j--;
if (j<0) {
j=getRowCount()-1;
}
}
}
column = i;
row = j;
}
else if (o.equals("scrolDownChangeSelection")) {
boolean found = false;
int i = row + 1;
int j = column;
while (!found) {
while (i
if (isCellNavigatable(i, j)) {
found = true;
break;
}
i++;
}
if (!found) {
i = 0;
j++;
if (j>=getRowCount()) {
j=0;
}
}
if (i==row && j==column) { //full table scan complete
break;
}
}
column = j;
row = i;
}
else if (o.equals("scrolUpChangeSelection")) {
boolean found = false;
int i = row - 1;
int j = column;
if (i<0) {
i = getRowCount()-1;
j--;
}
if (j<0) {
j=getColumnCount()-1;
}
while (!found) {
if (j==column && i==row) { //full table scan complete
break;
}
while (i>=0) {
if (isCellNavigatable(i, j)) {
found = true;
break;
}
i--;
}
if (!found) {
i = getRowCount()-1;
j--;
if (j<0) {
j=getColumnCount()-1;
}
}
}
column = j;
row = i;
}
super.changeSelection(row, column, toggle, extend);
}
@Override
public void updateUI() {
if (UIManager.get("BasicNavigatableTableUI")==null) {
UIManager.put("BasicNavigatableTableUI", "grid.BasicNavigatableTableUI");
UIManager.put("grid.BasicNavigatableTableUI", BasicNavigatableTableUI.class);
}
final ComponentUI newUI = UIManager.getUI(this);
setUI(newUI);
}
public String getUIClassID() {
return "BasicNavigatableTableUI";
}
private KeyStroke keyStroke;
}
Заметьте, что в начале changeSelection при некоторых условиях (например, управление навигацией отключено в модели: isNavigationOn() возвращает false), то управление передается родительскому методу и начинают действовать обработчики клавиатурных сокращений по умолчанию.
No comments :
Post a Comment