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 */