|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package javax.swing.tree; |
|
|
|
import java.beans.PropertyChangeListener; |
|
import java.io.*; |
|
import java.util.ArrayList; |
|
import java.util.BitSet; |
|
import java.util.Enumeration; |
|
import java.util.EventListener; |
|
import java.util.Hashtable; |
|
import java.util.List; |
|
import java.util.Vector; |
|
import javax.swing.event.*; |
|
import javax.swing.DefaultListSelectionModel; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@SuppressWarnings("serial") |
|
public class DefaultTreeSelectionModel implements Cloneable, Serializable, TreeSelectionModel |
|
{ |
|
|
|
public static final String SELECTION_MODE_PROPERTY = "selectionMode"; |
|
|
|
|
|
protected SwingPropertyChangeSupport changeSupport; |
|
|
|
|
|
* currently selected. */ |
|
protected TreePath[] selection; |
|
|
|
|
|
protected EventListenerList listenerList = new EventListenerList(); |
|
|
|
|
|
transient protected RowMapper rowMapper; |
|
|
|
|
|
* to map from a TreePath to a row, and the value is then placed here. */ |
|
protected DefaultListSelectionModel listSelectionModel; |
|
|
|
|
|
|
|
*/ |
|
protected int selectionMode; |
|
|
|
|
|
protected TreePath leadPath; |
|
|
|
protected int leadIndex; |
|
|
|
protected int leadRow; |
|
|
|
|
|
|
|
*/ |
|
private Hashtable<TreePath, Boolean> uniquePaths; |
|
private Hashtable<TreePath, Boolean> lastPaths; |
|
private TreePath[] tempPaths; |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public DefaultTreeSelectionModel() { |
|
listSelectionModel = new DefaultListSelectionModel(); |
|
selectionMode = DISCONTIGUOUS_TREE_SELECTION; |
|
leadIndex = leadRow = -1; |
|
uniquePaths = new Hashtable<TreePath, Boolean>(); |
|
lastPaths = new Hashtable<TreePath, Boolean>(); |
|
tempPaths = new TreePath[1]; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public void setRowMapper(RowMapper newMapper) { |
|
rowMapper = newMapper; |
|
resetRowSelection(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public RowMapper getRowMapper() { |
|
return rowMapper; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setSelectionMode(int mode) { |
|
int oldMode = selectionMode; |
|
|
|
selectionMode = mode; |
|
if(selectionMode != TreeSelectionModel.SINGLE_TREE_SELECTION && |
|
selectionMode != TreeSelectionModel.CONTIGUOUS_TREE_SELECTION && |
|
selectionMode != TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION) |
|
selectionMode = TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION; |
|
if(oldMode != selectionMode && changeSupport != null) |
|
changeSupport.firePropertyChange(SELECTION_MODE_PROPERTY, |
|
Integer.valueOf(oldMode), |
|
Integer.valueOf(selectionMode)); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public int getSelectionMode() { |
|
return selectionMode; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setSelectionPath(TreePath path) { |
|
if(path == null) |
|
setSelectionPaths(null); |
|
else { |
|
TreePath[] newPaths = new TreePath[1]; |
|
|
|
newPaths[0] = path; |
|
setSelectionPaths(newPaths); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setSelectionPaths(TreePath[] pPaths) { |
|
int newCount, newCounter, oldCount, oldCounter; |
|
TreePath[] paths = pPaths; |
|
|
|
if(paths == null) |
|
newCount = 0; |
|
else |
|
newCount = paths.length; |
|
if(selection == null) |
|
oldCount = 0; |
|
else |
|
oldCount = selection.length; |
|
if((newCount + oldCount) != 0) { |
|
if(selectionMode == TreeSelectionModel.SINGLE_TREE_SELECTION) { |
|
|
|
first. */ |
|
if(newCount > 1) { |
|
paths = new TreePath[1]; |
|
paths[0] = pPaths[0]; |
|
newCount = 1; |
|
} |
|
} |
|
else if(selectionMode == |
|
TreeSelectionModel.CONTIGUOUS_TREE_SELECTION) { |
|
|
|
only select the first path item. */ |
|
if(newCount > 0 && !arePathsContiguous(paths)) { |
|
paths = new TreePath[1]; |
|
paths[0] = pPaths[0]; |
|
newCount = 1; |
|
} |
|
} |
|
|
|
TreePath beginLeadPath = leadPath; |
|
Vector<PathPlaceHolder> cPaths = new Vector<PathPlaceHolder>(newCount + oldCount); |
|
List<TreePath> newSelectionAsList = |
|
new ArrayList<TreePath>(newCount); |
|
|
|
lastPaths.clear(); |
|
leadPath = null; |
|
|
|
for(newCounter = 0; newCounter < newCount; newCounter++) { |
|
TreePath path = paths[newCounter]; |
|
if (path != null && lastPaths.get(path) == null) { |
|
lastPaths.put(path, Boolean.TRUE); |
|
if (uniquePaths.get(path) == null) { |
|
cPaths.addElement(new PathPlaceHolder(path, true)); |
|
} |
|
leadPath = path; |
|
newSelectionAsList.add(path); |
|
} |
|
} |
|
|
|
TreePath[] newSelection = newSelectionAsList.toArray( |
|
new TreePath[newSelectionAsList.size()]); |
|
|
|
|
|
for(oldCounter = 0; oldCounter < oldCount; oldCounter++) |
|
if(selection[oldCounter] != null && |
|
lastPaths.get(selection[oldCounter]) == null) |
|
cPaths.addElement(new PathPlaceHolder |
|
(selection[oldCounter], false)); |
|
|
|
selection = newSelection; |
|
|
|
Hashtable<TreePath, Boolean> tempHT = uniquePaths; |
|
|
|
uniquePaths = lastPaths; |
|
lastPaths = tempHT; |
|
lastPaths.clear(); |
|
|
|
|
|
insureUniqueness(); |
|
|
|
updateLeadIndex(); |
|
|
|
resetRowSelection(); |
|
|
|
if(cPaths.size() > 0) |
|
notifyPathChange(cPaths, beginLeadPath); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void addSelectionPath(TreePath path) { |
|
if(path != null) { |
|
TreePath[] toAdd = new TreePath[1]; |
|
|
|
toAdd[0] = path; |
|
addSelectionPaths(toAdd); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void addSelectionPaths(TreePath[] paths) { |
|
int newPathLength = ((paths == null) ? 0 : paths.length); |
|
|
|
if(newPathLength > 0) { |
|
if(selectionMode == TreeSelectionModel.SINGLE_TREE_SELECTION) { |
|
setSelectionPaths(paths); |
|
} |
|
else if(selectionMode == TreeSelectionModel. |
|
CONTIGUOUS_TREE_SELECTION && !canPathsBeAdded(paths)) { |
|
if(arePathsContiguous(paths)) { |
|
setSelectionPaths(paths); |
|
} |
|
else { |
|
TreePath[] newPaths = new TreePath[1]; |
|
|
|
newPaths[0] = paths[0]; |
|
setSelectionPaths(newPaths); |
|
} |
|
} |
|
else { |
|
int counter, validCount; |
|
int oldCount; |
|
TreePath beginLeadPath = leadPath; |
|
Vector<PathPlaceHolder> cPaths = null; |
|
|
|
if(selection == null) |
|
oldCount = 0; |
|
else |
|
oldCount = selection.length; |
|
|
|
selection. */ |
|
lastPaths.clear(); |
|
for(counter = 0, validCount = 0; counter < newPathLength; |
|
counter++) { |
|
if(paths[counter] != null) { |
|
if (uniquePaths.get(paths[counter]) == null) { |
|
validCount++; |
|
if(cPaths == null) |
|
cPaths = new Vector<PathPlaceHolder>(); |
|
cPaths.addElement(new PathPlaceHolder |
|
(paths[counter], true)); |
|
uniquePaths.put(paths[counter], Boolean.TRUE); |
|
lastPaths.put(paths[counter], Boolean.TRUE); |
|
} |
|
leadPath = paths[counter]; |
|
} |
|
} |
|
|
|
if(leadPath == null) { |
|
leadPath = beginLeadPath; |
|
} |
|
|
|
if(validCount > 0) { |
|
TreePath newSelection[] = new TreePath[oldCount + |
|
validCount]; |
|
|
|
|
|
if(oldCount > 0) |
|
System.arraycopy(selection, 0, newSelection, 0, |
|
oldCount); |
|
if(validCount != paths.length) { |
|
|
|
the selection. */ |
|
Enumeration<TreePath> newPaths = lastPaths.keys(); |
|
|
|
counter = oldCount; |
|
while (newPaths.hasMoreElements()) { |
|
newSelection[counter++] = newPaths.nextElement(); |
|
} |
|
} |
|
else { |
|
System.arraycopy(paths, 0, newSelection, oldCount, |
|
validCount); |
|
} |
|
|
|
selection = newSelection; |
|
|
|
insureUniqueness(); |
|
|
|
updateLeadIndex(); |
|
|
|
resetRowSelection(); |
|
|
|
notifyPathChange(cPaths, beginLeadPath); |
|
} |
|
else |
|
leadPath = beginLeadPath; |
|
lastPaths.clear(); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void removeSelectionPath(TreePath path) { |
|
if(path != null) { |
|
TreePath[] rPath = new TreePath[1]; |
|
|
|
rPath[0] = path; |
|
removeSelectionPaths(rPath); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void removeSelectionPaths(TreePath[] paths) { |
|
if (paths != null && selection != null && paths.length > 0) { |
|
if(!canPathsBeRemoved(paths)) { |
|
|
|
clearSelection(); |
|
} |
|
else { |
|
Vector<PathPlaceHolder> pathsToRemove = null; |
|
|
|
|
|
for (int removeCounter = paths.length - 1; removeCounter >= 0; |
|
removeCounter--) { |
|
if(paths[removeCounter] != null) { |
|
if (uniquePaths.get(paths[removeCounter]) != null) { |
|
if(pathsToRemove == null) |
|
pathsToRemove = new Vector<PathPlaceHolder>(paths.length); |
|
uniquePaths.remove(paths[removeCounter]); |
|
pathsToRemove.addElement(new PathPlaceHolder |
|
(paths[removeCounter], false)); |
|
} |
|
} |
|
} |
|
if(pathsToRemove != null) { |
|
int removeCount = pathsToRemove.size(); |
|
TreePath beginLeadPath = leadPath; |
|
|
|
if(removeCount == selection.length) { |
|
selection = null; |
|
} |
|
else { |
|
Enumeration<TreePath> pEnum = uniquePaths.keys(); |
|
int validCount = 0; |
|
|
|
selection = new TreePath[selection.length - |
|
removeCount]; |
|
while (pEnum.hasMoreElements()) { |
|
selection[validCount++] = pEnum.nextElement(); |
|
} |
|
} |
|
if (leadPath != null && |
|
uniquePaths.get(leadPath) == null) { |
|
if (selection != null) { |
|
leadPath = selection[selection.length - 1]; |
|
} |
|
else { |
|
leadPath = null; |
|
} |
|
} |
|
else if (selection != null) { |
|
leadPath = selection[selection.length - 1]; |
|
} |
|
else { |
|
leadPath = null; |
|
} |
|
updateLeadIndex(); |
|
|
|
resetRowSelection(); |
|
|
|
notifyPathChange(pathsToRemove, beginLeadPath); |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public TreePath getSelectionPath() { |
|
if (selection != null && selection.length > 0) { |
|
return selection[0]; |
|
} |
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public TreePath[] getSelectionPaths() { |
|
if(selection != null) { |
|
int pathSize = selection.length; |
|
TreePath[] result = new TreePath[pathSize]; |
|
|
|
System.arraycopy(selection, 0, result, 0, pathSize); |
|
return result; |
|
} |
|
return new TreePath[0]; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public int getSelectionCount() { |
|
return (selection == null) ? 0 : selection.length; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean isPathSelected(TreePath path) { |
|
return (path != null) ? (uniquePaths.get(path) != null) : false; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public boolean isSelectionEmpty() { |
|
return (selection == null || selection.length == 0); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public void clearSelection() { |
|
if (selection != null && selection.length > 0) { |
|
int selSize = selection.length; |
|
boolean[] newness = new boolean[selSize]; |
|
|
|
for(int counter = 0; counter < selSize; counter++) |
|
newness[counter] = false; |
|
|
|
TreeSelectionEvent event = new TreeSelectionEvent |
|
(this, selection, newness, leadPath, null); |
|
|
|
leadPath = null; |
|
leadIndex = leadRow = -1; |
|
uniquePaths.clear(); |
|
selection = null; |
|
resetRowSelection(); |
|
fireValueChanged(event); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void addTreeSelectionListener(TreeSelectionListener x) { |
|
listenerList.add(TreeSelectionListener.class, x); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void removeTreeSelectionListener(TreeSelectionListener x) { |
|
listenerList.remove(TreeSelectionListener.class, x); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public TreeSelectionListener[] getTreeSelectionListeners() { |
|
return listenerList.getListeners(TreeSelectionListener.class); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
protected void fireValueChanged(TreeSelectionEvent e) { |
|
|
|
Object[] listeners = listenerList.getListenerList(); |
|
// TreeSelectionEvent e = null; |
|
// Process the listeners last to first, notifying |
|
|
|
for (int i = listeners.length-2; i>=0; i-=2) { |
|
if (listeners[i]==TreeSelectionListener.class) { |
|
// Lazily create the event: |
|
// if (e == null) |
|
|
|
((TreeSelectionListener)listeners[i+1]).valueChanged(e); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public <T extends EventListener> T[] getListeners(Class<T> listenerType) { |
|
return listenerList.getListeners(listenerType); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public int[] getSelectionRows() { |
|
// This is currently rather expensive. Needs |
|
|
|
if (rowMapper != null && selection != null && selection.length > 0) { |
|
int[] rows = rowMapper.getRowsForPaths(selection); |
|
|
|
if (rows != null) { |
|
int invisCount = 0; |
|
|
|
for (int counter = rows.length - 1; counter >= 0; counter--) { |
|
if (rows[counter] == -1) { |
|
invisCount++; |
|
} |
|
} |
|
if (invisCount > 0) { |
|
if (invisCount == rows.length) { |
|
rows = null; |
|
} |
|
else { |
|
int[] tempRows = new int[rows.length - invisCount]; |
|
|
|
for (int counter = rows.length - 1, visCounter = 0; |
|
counter >= 0; counter--) { |
|
if (rows[counter] != -1) { |
|
tempRows[visCounter++] = rows[counter]; |
|
} |
|
} |
|
rows = tempRows; |
|
} |
|
} |
|
} |
|
return rows; |
|
} |
|
return new int[0]; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public int getMinSelectionRow() { |
|
return listSelectionModel.getMinSelectionIndex(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public int getMaxSelectionRow() { |
|
return listSelectionModel.getMaxSelectionIndex(); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public boolean isRowSelected(int row) { |
|
return listSelectionModel.isSelectedIndex(row); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void resetRowSelection() { |
|
listSelectionModel.clearSelection(); |
|
if(selection != null && rowMapper != null) { |
|
int aRow; |
|
int validCount = 0; |
|
int[] rows = rowMapper.getRowsForPaths(selection); |
|
|
|
for(int counter = 0, maxCounter = selection.length; |
|
counter < maxCounter; counter++) { |
|
aRow = rows[counter]; |
|
if(aRow != -1) { |
|
listSelectionModel.addSelectionInterval(aRow, aRow); |
|
} |
|
} |
|
if(leadIndex != -1 && rows != null) { |
|
leadRow = rows[leadIndex]; |
|
} |
|
else if (leadPath != null) { |
|
|
|
tempPaths[0] = leadPath; |
|
rows = rowMapper.getRowsForPaths(tempPaths); |
|
leadRow = (rows != null) ? rows[0] : -1; |
|
} |
|
else { |
|
leadRow = -1; |
|
} |
|
insureRowContinuity(); |
|
|
|
} |
|
else |
|
leadRow = -1; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public int getLeadSelectionRow() { |
|
return leadRow; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public TreePath getLeadSelectionPath() { |
|
return leadPath; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public synchronized void addPropertyChangeListener( |
|
PropertyChangeListener listener) { |
|
if (changeSupport == null) { |
|
changeSupport = new SwingPropertyChangeSupport(this); |
|
} |
|
changeSupport.addPropertyChangeListener(listener); |
|
} |
|
|
|
/** |
|
* Removes a PropertyChangeListener from the listener list. |
|
* This removes a PropertyChangeListener that was registered |
|
* for all properties. |
|
* |
|
* @param listener the PropertyChangeListener to be removed |
|
*/ |
|
|
|
public synchronized void removePropertyChangeListener( |
|
PropertyChangeListener listener) { |
|
if (changeSupport == null) { |
|
return; |
|
} |
|
changeSupport.removePropertyChangeListener(listener); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public PropertyChangeListener[] getPropertyChangeListeners() { |
|
if (changeSupport == null) { |
|
return new PropertyChangeListener[0]; |
|
} |
|
return changeSupport.getPropertyChangeListeners(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
protected void insureRowContinuity() { |
|
if(selectionMode == TreeSelectionModel.CONTIGUOUS_TREE_SELECTION && |
|
selection != null && rowMapper != null) { |
|
DefaultListSelectionModel lModel = listSelectionModel; |
|
int min = lModel.getMinSelectionIndex(); |
|
|
|
if(min != -1) { |
|
for(int counter = min, |
|
maxCounter = lModel.getMaxSelectionIndex(); |
|
counter <= maxCounter; counter++) { |
|
if(!lModel.isSelectedIndex(counter)) { |
|
if(counter == min) { |
|
clearSelection(); |
|
} |
|
else { |
|
TreePath[] newSel = new TreePath[counter - min]; |
|
int selectionIndex[] = rowMapper.getRowsForPaths(selection); |
|
// find the actual selection pathes corresponded to the |
|
|
|
for (int i = 0; i < selectionIndex.length; i++) { |
|
if (selectionIndex[i]<counter) { |
|
newSel[selectionIndex[i]-min] = selection[i]; |
|
} |
|
} |
|
setSelectionPaths(newSel); |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
else if(selectionMode == TreeSelectionModel.SINGLE_TREE_SELECTION && |
|
selection != null && selection.length > 1) { |
|
setSelectionPath(selection[0]); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
protected boolean arePathsContiguous(TreePath[] paths) { |
|
if(rowMapper == null || paths.length < 2) |
|
return true; |
|
else { |
|
BitSet bitSet = new BitSet(32); |
|
int anIndex, counter, min; |
|
int pathCount = paths.length; |
|
int validCount = 0; |
|
TreePath[] tempPath = new TreePath[1]; |
|
|
|
tempPath[0] = paths[0]; |
|
min = rowMapper.getRowsForPaths(tempPath)[0]; |
|
for(counter = 0; counter < pathCount; counter++) { |
|
if(paths[counter] != null) { |
|
tempPath[0] = paths[counter]; |
|
int[] rows = rowMapper.getRowsForPaths(tempPath); |
|
if (rows == null) { |
|
return false; |
|
} |
|
anIndex = rows[0]; |
|
if(anIndex == -1 || anIndex < (min - pathCount) || |
|
anIndex > (min + pathCount)) |
|
return false; |
|
if(anIndex < min) |
|
min = anIndex; |
|
if(!bitSet.get(anIndex)) { |
|
bitSet.set(anIndex); |
|
validCount++; |
|
} |
|
} |
|
} |
|
int maxCounter = validCount + min; |
|
|
|
for(counter = min; counter < maxCounter; counter++) |
|
if(!bitSet.get(counter)) |
|
return false; |
|
} |
|
return true; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
protected boolean canPathsBeAdded(TreePath[] paths) { |
|
if(paths == null || paths.length == 0 || rowMapper == null || |
|
selection == null || selectionMode == |
|
TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION) |
|
return true; |
|
else { |
|
BitSet bitSet = new BitSet(); |
|
DefaultListSelectionModel lModel = listSelectionModel; |
|
int anIndex; |
|
int counter; |
|
int min = lModel.getMinSelectionIndex(); |
|
int max = lModel.getMaxSelectionIndex(); |
|
TreePath[] tempPath = new TreePath[1]; |
|
|
|
if(min != -1) { |
|
for(counter = min; counter <= max; counter++) { |
|
if(lModel.isSelectedIndex(counter)) |
|
bitSet.set(counter); |
|
} |
|
} |
|
else { |
|
tempPath[0] = paths[0]; |
|
min = max = rowMapper.getRowsForPaths(tempPath)[0]; |
|
} |
|
for(counter = paths.length - 1; counter >= 0; counter--) { |
|
if(paths[counter] != null) { |
|
tempPath[0] = paths[counter]; |
|
int[] rows = rowMapper.getRowsForPaths(tempPath); |
|
if (rows == null) { |
|
return false; |
|
} |
|
anIndex = rows[0]; |
|
min = Math.min(anIndex, min); |
|
max = Math.max(anIndex, max); |
|
if(anIndex == -1) |
|
return false; |
|
bitSet.set(anIndex); |
|
} |
|
} |
|
for(counter = min; counter <= max; counter++) |
|
if(!bitSet.get(counter)) |
|
return false; |
|
} |
|
return true; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
protected boolean canPathsBeRemoved(TreePath[] paths) { |
|
if(rowMapper == null || selection == null || |
|
selectionMode == TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION) |
|
return true; |
|
else { |
|
BitSet bitSet = new BitSet(); |
|
int counter; |
|
int pathCount = paths.length; |
|
int anIndex; |
|
int min = -1; |
|
int validCount = 0; |
|
TreePath[] tempPath = new TreePath[1]; |
|
int[] rows; |
|
|
|
|
|
lastPaths.clear(); |
|
for (counter = 0; counter < pathCount; counter++) { |
|
if (paths[counter] != null) { |
|
lastPaths.put(paths[counter], Boolean.TRUE); |
|
} |
|
} |
|
for(counter = selection.length - 1; counter >= 0; counter--) { |
|
if(lastPaths.get(selection[counter]) == null) { |
|
tempPath[0] = selection[counter]; |
|
rows = rowMapper.getRowsForPaths(tempPath); |
|
if(rows != null && rows[0] != -1 && !bitSet.get(rows[0])) { |
|
validCount++; |
|
if(min == -1) |
|
min = rows[0]; |
|
else |
|
min = Math.min(min, rows[0]); |
|
bitSet.set(rows[0]); |
|
} |
|
} |
|
} |
|
lastPaths.clear(); |
|
|
|
if(validCount > 1) { |
|
for(counter = min + validCount - 1; counter >= min; |
|
counter--) |
|
if(!bitSet.get(counter)) |
|
return false; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Deprecated |
|
protected void notifyPathChange(Vector<?> changedPaths, |
|
TreePath oldLeadSelection) { |
|
int cPathCount = changedPaths.size(); |
|
boolean[] newness = new boolean[cPathCount]; |
|
TreePath[] paths = new TreePath[cPathCount]; |
|
PathPlaceHolder placeholder; |
|
|
|
for(int counter = 0; counter < cPathCount; counter++) { |
|
placeholder = (PathPlaceHolder) changedPaths.elementAt(counter); |
|
newness[counter] = placeholder.isNew; |
|
paths[counter] = placeholder.path; |
|
} |
|
|
|
TreeSelectionEvent event = new TreeSelectionEvent |
|
(this, paths, newness, oldLeadSelection, leadPath); |
|
|
|
fireValueChanged(event); |
|
} |
|
|
|
|
|
|
|
*/ |
|
protected void updateLeadIndex() { |
|
if(leadPath != null) { |
|
if(selection == null) { |
|
leadPath = null; |
|
leadIndex = leadRow = -1; |
|
} |
|
else { |
|
leadRow = leadIndex = -1; |
|
for(int counter = selection.length - 1; counter >= 0; |
|
counter--) { |
|
// Can use == here since we know leadPath came from |
|
|
|
if(selection[counter] == leadPath) { |
|
leadIndex = counter; |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
else { |
|
leadIndex = -1; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
protected void insureUniqueness() { |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public String toString() { |
|
int selCount = getSelectionCount(); |
|
StringBuffer retBuffer = new StringBuffer(); |
|
int[] rows; |
|
|
|
if(rowMapper != null) |
|
rows = rowMapper.getRowsForPaths(selection); |
|
else |
|
rows = null; |
|
retBuffer.append(getClass().getName() + " " + hashCode() + " [ "); |
|
for(int counter = 0; counter < selCount; counter++) { |
|
if(rows != null) |
|
retBuffer.append(selection[counter].toString() + "@" + |
|
Integer.toString(rows[counter])+ " "); |
|
else |
|
retBuffer.append(selection[counter].toString() + " "); |
|
} |
|
retBuffer.append("]"); |
|
return retBuffer.toString(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public Object clone() throws CloneNotSupportedException { |
|
DefaultTreeSelectionModel clone = (DefaultTreeSelectionModel) |
|
super.clone(); |
|
|
|
clone.changeSupport = null; |
|
if(selection != null) { |
|
int selLength = selection.length; |
|
|
|
clone.selection = new TreePath[selLength]; |
|
System.arraycopy(selection, 0, clone.selection, 0, selLength); |
|
} |
|
clone.listenerList = new EventListenerList(); |
|
clone.listSelectionModel = (DefaultListSelectionModel) |
|
listSelectionModel.clone(); |
|
clone.uniquePaths = new Hashtable<TreePath, Boolean>(); |
|
clone.lastPaths = new Hashtable<TreePath, Boolean>(); |
|
clone.tempPaths = new TreePath[1]; |
|
return clone; |
|
} |
|
|
|
|
|
private void writeObject(ObjectOutputStream s) throws IOException { |
|
Object[] tValues; |
|
|
|
s.defaultWriteObject(); |
|
|
|
if(rowMapper != null && rowMapper instanceof Serializable) { |
|
tValues = new Object[2]; |
|
tValues[0] = "rowMapper"; |
|
tValues[1] = rowMapper; |
|
} |
|
else |
|
tValues = new Object[0]; |
|
s.writeObject(tValues); |
|
} |
|
|
|
|
|
private void readObject(ObjectInputStream s) |
|
throws IOException, ClassNotFoundException { |
|
Object[] tValues; |
|
|
|
s.defaultReadObject(); |
|
|
|
tValues = (Object[])s.readObject(); |
|
|
|
if(tValues.length > 0 && tValues[0].equals("rowMapper")) |
|
rowMapper = (RowMapper)tValues[1]; |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
class PathPlaceHolder { |
|
protected boolean isNew; |
|
protected TreePath path; |
|
|
|
PathPlaceHolder(TreePath path, boolean isNew) { |
|
this.path = path; |
|
this.isNew = isNew; |
|
} |
|
} |