package iiuf.swing;
import java.util.ArrayList;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetListener;
import java.awt.dnd.DragSource;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import javax.swing.JPanel;
import javax.swing.JList;
import javax.swing.JPopupMenu;
import javax.swing.ListModel;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JComponent;
import javax.swing.Icon;
import javax.swing.UIManager;
import javax.swing.DefaultListModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.metal.MetalIconFactory;
import iiuf.awt.Awt;
import iiuf.log.Log;
import iiuf.util.ProgressListener;
import iiuf.util.ProgressWatcher;
import iiuf.util.EventListenerList;
/**
Chooser tree view implementation, looks like a file chooser.
(c) 2000, 2001, IIUF, DIUF<p>
@author $Author: ohitz $
@version $Name: $ $Revision: 1.1 $
*/
public class ChooserTreeView
extends
JPanel
implements
TreeView,
ProgressListener,
ChangeListener
{
private static final Border NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 1);
ListTreeModel tree;
ButtonTreePathView pathView = new ButtonTreePathView(tree);
JList content = new JList();
Object node;
JScrollPane csp;
ContextMenuManager ctxmgr;
EventListenerList listeners = new EventListenerList();
boolean ignoreRepaints;
public ChooserTreeView() {
this(null);
}
public ChooserTreeView(TreeModel model) {
this(model, null);
}
public ChooserTreeView(TreeModel model, TreePath rootPath) {
setLayout(new BorderLayout());
JScrollPane pathSP = new JScrollPane(pathView);
pathView.addChangeListener(this);
pathSP.setHorizontalScrollBarPolicy(pathSP.HORIZONTAL_SCROLLBAR_ALWAYS);
pathSP.setVerticalScrollBarPolicy(pathSP.VERTICAL_SCROLLBAR_NEVER);
add(pathSP, BorderLayout.NORTH);
csp = new JScrollPane(content);
csp.setHorizontalScrollBarPolicy(csp.HORIZONTAL_SCROLLBAR_AS_NEEDED);
csp.setVerticalScrollBarPolicy(csp.VERTICAL_SCROLLBAR_NEVER);
add(csp, BorderLayout.CENTER);
if(model != null) setModel(model, rootPath);
content.setCellRenderer(new CellRenderer());
content.addMouseListener(Awt.asyncWrapper(mouseAdapter));
content.setUI(new MultiColumnListUI());
}
public void addRootNodeChangeListener(ChangeListener l) {
listeners.add(ChangeListener.class, l);
}
public void addRootNodeChangeListener(ChangeListener l, boolean weak) {
listeners.add(ChangeListener.class, l, weak);
}
public void removeRootNodeChangeListener(ChangeListener l) {
listeners.remove(ChangeListener.class, l);
}
public void stateChanged(ChangeEvent e) {
if(lastNode() == node) return;
synchronized(this) {
if(setupContent) return;
setupContent = true;
}
node = lastNode();
ListModel m = tree.getListModel(node, true);
content.setModel(m == null ? new DefaultListModel() : m);
synchronized(this) {
setupContent = false;
}
}
public void setModel(TreeModel model) {
setModel(model, null);
}
public void setModel(TreeModel model, TreePath rootPath) {
pathView.setModel(model);
if(rootPath == null)
rootPath = new TreePath(model.getRoot());
tree = new ListTreeModel(model);
pathView.setPath(rootPath, true);
}
public TreeModel getModel() {
return tree;
}
public Object getViewRoot() {
return pathView.getViewRoot();
}
public void makeVisible(TreePath treepath) {
if(treepath == null) return;
if(tree.isLeaf(treepath.getLastPathComponent()))
pathView.setPath(treepath.getParentPath());
else
pathView.setPath(treepath);
}
public TreePath getMostVisiblePath() {
return pathView.getPath();
}
public boolean isVisible(TreePath path) {
Object node = path.getLastPathComponent();
if(tree.isLeaf(node)) {
ListModel model = content.getModel();
for(int i = 0; i < model.getSize(); i++)
if(model.getElementAt(i).equals(node))
return true;
return false;
} else
return pathView.getPath().equals(path);
}
public TreePath getSelectionPath() {
TreePath[] tp = getSelectionPaths();
return tp.length > 0 ? tp[0] : null;
}
public TreePath[] getSelectionPaths() {
int[] idxs = content.getSelectedIndices();
TreePath[] result = new TreePath[idxs.length];
for(int i = 0; i < idxs.length; i++)
result[i] = pathView.getPath().pathByAddingChild(content.getModel().getElementAt(idxs[i]));
return result;
}
public void setSelectionPath(TreePath path) {
if(path == null) return;
setSelectionPaths(new TreePath[] {path});
}
public void setSelectionPaths(TreePath[] path) {
if(path == null || path.length == 0) return;
TreePath maxPath = path[0];
for(int i = 0; i < path.length; i++)
if(path[i].getPathCount() > maxPath.getPathCount())
maxPath = path[i];
maxPath = maxPath.getParentPath();
makeVisible(maxPath);
minSelected = Integer.MAX_VALUE;
for(int i = 0; i < path.length; i++)
if(path[i].getParentPath().equals(maxPath))
select(path[i].getLastPathComponent());
}
private int minSelected = Integer.MAX_VALUE;
private void select(Object node) {
int count = content.getModel().getSize();
for(int i = 0; i < count; i++)
if(content.getModel().getElementAt(i).equals(node)) {
content.getSelectionModel().addSelectionInterval(i, i);
if(i < minSelected) {
content.ensureIndexIsVisible(i);
minSelected = i;
}
}
}
public void clearSelection() {
content.clearSelection();
}
private Object lastNode() {
return pathView.getPath().getLastPathComponent();
}
private MouseAdapter mouseAdapter = new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if(e.getClickCount() == 2 && ((e.getModifiers() & e.BUTTON1_MASK) == e.BUTTON1_MASK)) {
ProgressWatcher.watch(ChooserTreeView.this);
int idx = content.locationToIndex(e.getPoint());
if(idx < 0) return;
Object n = content.getModel().getElementAt(idx);
if(!tree.isLeaf(n))
pathView.setPath(pathView.getPath().pathByAddingChild(n));
}
}
};
public Object locationToObject(Component component, Point location) {
int idx = content.locationToIndex(location);
return idx < 0 ? null : content.getModel().getElementAt(idx);
}
public Component getComponent() {
return content;
}
public void setContextMenuManager(ContextMenuManager manager) {
ctxmgr = manager;
}
boolean setupContent;
private void setupContent() {
}
public void operationStart(String desc) {}
public void operationProgress(int amount, int of) {
if(amount == 0) Awt.setCursor(this, Cursor.WAIT_CURSOR);
}
public void operationStop() {
Awt.setCursor(this, Cursor.DEFAULT_CURSOR);
}
DragGestureRecognizer sourceRecognizer;
DragGestureListener srcListener;
public void enableDrag(int sourceActions, DragGestureListener sourceListener) {
disableDrag();
sourceRecognizer = DragSource.getDefaultDragSource().
createDefaultDragGestureRecognizer(content, sourceActions, sourceListener);
srcListener = sourceListener;
}
DropTarget dropTarget;
DropTargetListener trgtListener;
public void enableDrop(int targetActions, DropTargetListener targetListener) {
disableDrop();
dropTarget = new DropTarget(content, targetActions, targetListener);
trgtListener = targetListener;
}
public void disableDrag() {
if(sourceRecognizer != null)
sourceRecognizer.removeDragGestureListener(srcListener);
sourceRecognizer = null;
srcListener = null;
System.gc();
}
public void disableDrop() {
if(dropTarget != null)
dropTarget.removeDropTargetListener(trgtListener);
dropTarget = null;
trgtListener = null;
System.gc();
}
class CellRenderer
extends
DefaultListCellRenderer
{
public Component getListCellRendererComponent(JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus)
{
DefaultListCellRenderer result =
(DefaultListCellRenderer)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
result.setIcon(tree.isLeaf(value) ?
MetalIconFactory.getTreeLeafIcon() :
MetalIconFactory.getTreeFolderIcon());
return result;
}
}
}
/*
$Log: ChooserTreeView.java,v $
Revision 1.1 2002/07/11 12:09:52 ohitz
Initial checkin
Revision 1.8 2001/01/14 13:21:13 schubige
Win NT update
Revision 1.7 2001/01/12 08:26:20 schubige
TJGUI update and some TreeView bug fixes
Revision 1.6 2001/01/04 16:28:38 schubige
Header update for 2001 and DIUF
Revision 1.5 2001/01/03 08:30:39 schubige
graph stuff beta
Revision 1.4 2000/11/09 07:48:43 schubige
early checkin for DCJava
Revision 1.3 2000/10/10 16:32:12 schubige
Added subtree display to TreeView, fixed some bugs
Revision 1.2 2000/10/03 08:39:38 schubige
Added tree view and contect menu stuff
Revision 1.1 2000/08/17 16:22:14 schubige
Swing cleanup & TreeView added
*/