/* * Copyright (C) 2006-2007 Sun Microsystems, Inc. All rights reserved. Use is * subject to license terms. */ package org.jdesktop.swingbinding.adapters; import java.beans.*; import javax.swing.*; import org.jdesktop.beansbinding.ext.BeanAdapterProvider; import org.jdesktop.swingbinding.impl.ListBindingManager; import javax.swing.event.*; import javax.swing.table.*; import java.util.HashMap; import java.util.List; import java.util.ArrayList; import java.lang.reflect.InvocationTargetException; /** * @author Shannon Hickey */ public final class JTableAdapterProvider implements BeanAdapterProvider { private static final String SELECTED_ELEMENT_P = "selectedElement"; private static final String SELECTED_ELEMENTS_P = "selectedElements"; private static final String SELECTED_ELEMENT_IA_P = SELECTED_ELEMENT_P + "_IGNORE_ADJUSTING"; private static final String SELECTED_ELEMENTS_IA_P = SELECTED_ELEMENTS_P + "_IGNORE_ADJUSTING"; private static boolean IS_JAVA_15 = System.getProperty("java.version").startsWith("1.5"); public final class Adapter extends BeanAdapterBase { private JTable table; private Handler handler; private Object cachedElementOrElements; private Adapter(JTable table, String property) { super(property); this.table = table; } private boolean isPlural() { return property == SELECTED_ELEMENTS_P || property == SELECTED_ELEMENTS_IA_P; } public Object getSelectedElement() { return JTableAdapterProvider.getSelectedElement(table); } public Object getSelectedElement_IGNORE_ADJUSTING() { return getSelectedElement(); } public List<Object> getSelectedElements() { return JTableAdapterProvider.getSelectedElements(table); } public List<Object> getSelectedElements_IGNORE_ADJUSTING() { return getSelectedElements(); } protected void listeningStarted() { handler = new Handler(); cachedElementOrElements = isPlural() ? getSelectedElements() : JTableAdapterProvider.getSelectedElement(table); table.addPropertyChangeListener("selectionModel", handler); table.getSelectionModel().addListSelectionListener(handler); } protected void listeningStopped() { table.getSelectionModel().removeListSelectionListener(handler); table.removePropertyChangeListener("selectionModel", handler); cachedElementOrElements = null; handler = null; } private class Handler implements ListSelectionListener, PropertyChangeListener { private void tableSelectionChanged() { Object oldElementOrElements = cachedElementOrElements; cachedElementOrElements = getSelectedElements(); firePropertyChange(oldElementOrElements, cachedElementOrElements); } public void valueChanged(ListSelectionEvent e) { if ((property == SELECTED_ELEMENT_IA_P || property == SELECTED_ELEMENTS_IA_P) && e.getValueIsAdjusting()) { return; } tableSelectionChanged(); } public void propertyChange(PropertyChangeEvent pce) { ((ListSelectionModel)pce.getOldValue()).removeListSelectionListener(handler); ((ListSelectionModel)pce.getNewValue()).addListSelectionListener(handler); tableSelectionChanged(); } } } private static int viewToModel(JTable table, int index) { // deal with sorting & filtering in 6.0 and up if (!IS_JAVA_15) { try { java.lang.reflect.Method m = table.getClass().getMethod("convertRowIndexToModel", int.class); index = (Integer)m.invoke(table, index); } catch (NoSuchMethodException nsme) { throw new AssertionError(nsme); } catch (IllegalAccessException iae) { throw new AssertionError(iae); } catch (InvocationTargetException ite) { Throwable cause = ite.getCause(); if (cause instanceof Error) { throw (Error)cause; } else { throw new RuntimeException(cause); } } } return index; } private static int modelToView(JTable table, int index) { // deal with sorting & filtering in 6.0 and up if (!IS_JAVA_15) { try { java.lang.reflect.Method m = table.getClass().getMethod("convertRowIndexToView", int.class); index = (Integer)m.invoke(table, index); } catch (NoSuchMethodException nsme) { throw new AssertionError(nsme); } catch (IllegalAccessException iae) { throw new AssertionError(iae); } catch (InvocationTargetException ite) { Throwable cause = ite.getCause(); if (cause instanceof Error) { throw (Error)cause; } else { throw new RuntimeException(cause); } } } return index; } private static List<Object> getSelectedElements(JTable table) { assert table != null; ListSelectionModel selectionModel = table.getSelectionModel(); int min = selectionModel.getMinSelectionIndex(); int max = selectionModel.getMaxSelectionIndex(); List<Object> newSelection; if (min < 0 || max < 0) { return new ArrayList<Object>(0); } ArrayList<Object> elements = new ArrayList<Object>(max - min + 1); for (int i = min; i <= max; i++) { if (selectionModel.isSelectedIndex(i)) { elements.add(getElement(table, i)); } } return elements; } private static Object getSelectedElement(JTable table) { assert table != null; // PENDING(shannonh) - more cases to consider int index = table.getSelectionModel().getLeadSelectionIndex(); index = table.getSelectionModel().isSelectedIndex(index) ? index : table.getSelectionModel().getMinSelectionIndex(); if (index == -1) { return null; } return getElement(table, index); } private static Object getElement(JTable table, int index) { index = viewToModel(table, index); TableModel model = table.getModel(); if (model instanceof ListBindingManager) { return ((ListBindingManager)model).getElement(index); } else { int columnCount = model.getColumnCount(); // PENDING(shannonh) - need to support editing values in this map! HashMap map = new HashMap(columnCount); for (int i = 0; i < columnCount; i++) { map.put("column" + i, model.getValueAt(index, i)); } return map; } } public boolean providesAdapter(Class<?> type, String property) { if (!JTable.class.isAssignableFrom(type)) { return false; } property = property.intern(); return property == SELECTED_ELEMENT_P || property == SELECTED_ELEMENT_IA_P || property == SELECTED_ELEMENTS_P || property == SELECTED_ELEMENTS_IA_P; } public Object createAdapter(Object source, String property) { if (!providesAdapter(source.getClass(), property)) { throw new IllegalArgumentException(); } return new Adapter((JTable)source, property); } public Class<?> getAdapterClass(Class<?> type) { return JTable.class.isAssignableFrom(type) ? JTableAdapterProvider.Adapter.class : null; } }