freehep-swing-2.0.3/ 0000755 0120103 0120103 00000000000 11275634131 015250 5 ustar mascellani mascellani freehep-swing-2.0.3/src/ 0000755 0120103 0120103 00000000000 11275634131 016037 5 ustar mascellani mascellani freehep-swing-2.0.3/src/test/ 0000755 0120103 0120103 00000000000 11275634131 017016 5 ustar mascellani mascellani freehep-swing-2.0.3/src/test/java/ 0000755 0120103 0120103 00000000000 11275634131 017737 5 ustar mascellani mascellani freehep-swing-2.0.3/src/test/java/org/ 0000755 0120103 0120103 00000000000 11275634131 020526 5 ustar mascellani mascellani freehep-swing-2.0.3/src/test/java/org/freehep/ 0000755 0120103 0120103 00000000000 11275634131 022144 5 ustar mascellani mascellani freehep-swing-2.0.3/src/test/java/org/freehep/swing/ 0000755 0120103 0120103 00000000000 11275634131 023273 5 ustar mascellani mascellani freehep-swing-2.0.3/src/test/java/org/freehep/swing/treetable/ 0000755 0120103 0120103 00000000000 11275634131 025242 5 ustar mascellani mascellani freehep-swing-2.0.3/src/test/java/org/freehep/swing/treetable/test/ 0000755 0120103 0120103 00000000000 11275634131 026221 5 ustar mascellani mascellani freehep-swing-2.0.3/src/test/java/org/freehep/swing/treetable/test/TreeTableExample2.java 0000644 0120103 0120103 00000036730 10466735775 032363 0 ustar mascellani mascellani package org.freehep.swing.treetable.test; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.text.NumberFormat; import javax.swing.ButtonGroup; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JRadioButtonMenuItem; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.SwingUtilities; import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.border.BevelBorder; import javax.swing.event.TableModelEvent; import javax.swing.event.TreeExpansionEvent; import javax.swing.event.TreeExpansionListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.tree.TreePath; import org.freehep.swing.treetable.JTreeTable; /** * Assembles the UI. The UI consists of a JTreeTable and a status label. * As nodes are loaded by the FileSystemModel2, in a background thread, * the status label updates as well as the renderer to draw the node that * is being loaded differently. * * @author Scott Violet * @author Philip Milne */ public class TreeTableExample2 { /** Number of instances of TreeTableExample2. */ protected static int ttCount; /** Model for the JTreeTable. */ protected FileSystemModel2 model; /** Used to represent the model. */ protected JTreeTable treeTable; /** Row the is being reloaded. */ protected int reloadRow; /** TreePath being reloaded. */ protected TreePath reloadPath; /** A counter increment as the Timer fies and the same path is * being reloaded. */ protected int reloadCounter; /** Timer used to update reload state. */ protected Timer timer; /** Used to indicate status. */ protected JLabel statusLabel; /** Frame containing everything. */ protected JFrame frame; /** Path created with. */ protected String path; public TreeTableExample2(String path) { this.path = path; ttCount++; frame = createFrame(); Container cPane = frame.getContentPane(); JMenuBar mb = createMenuBar(); model = createModel(path); treeTable = createTreeTable(); statusLabel = createStatusLabel(); cPane.add(new JScrollPane(treeTable)); cPane.add(statusLabel, BorderLayout.SOUTH); reloadRow = -1; frame.setJMenuBar(mb); frame.pack(); frame.setVisible(true); SwingUtilities.invokeLater(new Runnable() { public void run() { reload(model.getRoot()); } }); } /** * Creates and return a JLabel that is used to indicate the status * of loading. */ protected JLabel createStatusLabel() { JLabel retLabel = new JLabel(" "); retLabel.setHorizontalAlignment(JLabel.RIGHT); retLabel.setBorder(new BevelBorder(BevelBorder.LOWERED)); return retLabel; } /** * Creates and returns the instanceof JTreeTable that will be used. * This also creates, but does not start, the Timer that is used to * update the display as files are loaded. */ protected JTreeTable createTreeTable() { JTreeTable treeTable = new JTreeTable(model); treeTable.getColumnModel().getColumn(1).setCellRenderer (new IndicatorRenderer()); Reloader rl = new Reloader(); timer = new Timer(700, rl); timer.setRepeats(true); treeTable.getTree().addTreeExpansionListener(rl); return treeTable; } /** * Creates the FileSystemModel2 that will be used. */ protected FileSystemModel2 createModel(String path) { return new FileSystemModel2(path); } /** * Creates the JFrame that will contain everything. */ protected JFrame createFrame() { JFrame retFrame = new JFrame("TreeTable II"); retFrame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent we) { if (--ttCount == 0) { System.exit(0); } } }); return retFrame; } /** * Creates a menu bar. */ protected JMenuBar createMenuBar() { JMenu fileMenu = new JMenu("File"); JMenuItem menuItem; menuItem = new JMenuItem("Open"); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { JFileChooser fc = new JFileChooser(path); fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); int result = fc.showOpenDialog(frame); if (result == JFileChooser.APPROVE_OPTION) { String newPath = fc.getSelectedFile().getPath(); new TreeTableExample2(newPath); } } }); fileMenu.add(menuItem); fileMenu.addSeparator(); menuItem = new JMenuItem("Reload"); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { TreePath path = treeTable.getTree().getSelectionPath(); if (path != null) { model.stopLoading(); reload(path.getLastPathComponent()); } } }); fileMenu.add(menuItem); menuItem = new JMenuItem("Stop"); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { model.stopLoading(); } }); fileMenu.add(menuItem); fileMenu.addSeparator(); menuItem = new JMenuItem("Exit"); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { System.exit(0); } }); fileMenu.add(menuItem); // Create a menu bar JMenuBar menuBar = new JMenuBar(); menuBar.add(fileMenu); // Menu for the look and feels (lafs). UIManager.LookAndFeelInfo[] lafs = UIManager. getInstalledLookAndFeels(); ButtonGroup lafGroup = new ButtonGroup(); JMenu optionsMenu = new JMenu("Options"); menuBar.add(optionsMenu); for(int i = 0; i < lafs.length; i++) { JRadioButtonMenuItem rb = new JRadioButtonMenuItem(lafs[i]. getName()); optionsMenu.add(rb); rb.setSelected(UIManager.getLookAndFeel().getName().equals (lafs[i].getName())); rb.putClientProperty("UIKey", lafs[i]); rb.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent ae) { JRadioButtonMenuItem rb2 = (JRadioButtonMenuItem)ae. getSource(); if(rb2.isSelected()) { UIManager.LookAndFeelInfo info = (UIManager.LookAndFeelInfo) rb2.getClientProperty("UIKey"); try { UIManager.setLookAndFeel(info.getClassName()); SwingUtilities.updateComponentTreeUI(frame); } catch (Exception e) { System.err.println("unable to set UI " + e.getMessage()); } } } }); lafGroup.add(rb); } return menuBar; } /** * Invoked to reload the children of a particular node. This will * also restart the timer. */ protected void reload(Object node) { model.reloadChildren(node); if (!timer.isRunning()) { timer.start(); } } /** * Updates the status label based on reloadRow. */ protected void updateStatusLabel() { if (reloadPath != null) { statusLabel.setText("Reloading: " + model.getPath (reloadPath.getLastPathComponent())); if ((reloadCounter % 4) < 2) { statusLabel.setForeground(Color.red); } else { statusLabel.setForeground(Color.blue); } } else if (!model.isReloading()) { statusLabel.setText("Total Size: " + NumberFormat.getInstance(). format(model.getTotalSize(model.getRoot()))); statusLabel.setForeground(Color.black); } } /** * Reloader is the ActionListener used in the Timer. In response to * the timer updating it will reset the reloadRow/reloadPath and * generate the necessary event so that the display will update. It * also implements the TreeExpansionListener so that if the tree is * altered while loading the reloadRow is updated accordingly. */ class Reloader implements ActionListener, TreeExpansionListener { public void actionPerformed(ActionEvent ae) { if (!model.isReloading()) { // No longer loading. timer.stop(); if (reloadRow != -1) { generateChangeEvent(reloadRow); } reloadRow = -1; reloadPath = null; } else { // Still loading, see if paths changed. TreePath newPath = model.getPathLoading(); if (newPath == null) { // Hmm... Will usually indicate the reload thread // completed between time we asked if reloading. if (reloadRow != -1) { generateChangeEvent(reloadRow); } reloadRow = -1; reloadPath = null; } else { // Ok, valid path, see if matches last path. int newRow = treeTable.getTree().getRowForPath (newPath); if (newPath.equals(reloadPath)) { reloadCounter = (reloadCounter + 1) % 8; if (newRow != reloadRow) { int lastRow = reloadRow; reloadRow = newRow; generateChangeEvent(lastRow); } generateChangeEvent(reloadRow); } else { int lastRow = reloadRow; reloadCounter = 0; reloadRow = newRow; reloadPath = newPath; if (lastRow != reloadRow) { generateChangeEvent(lastRow); } generateChangeEvent(reloadRow); } } } updateStatusLabel(); } /** * Generates and update event for the specified row. FileSystemModel2 * could do this, but it would not know when the row has changed * as a result of expanding/collapsing nodes in the tree. */ protected void generateChangeEvent(int row) { if (row != -1) { AbstractTableModel tModel = (AbstractTableModel)treeTable. getModel(); tModel.fireTableChanged(new TableModelEvent (tModel, row, row, 1)); } } // // TreeExpansionListener // /** * Invoked when the tree has expanded. */ public void treeExpanded(TreeExpansionEvent te) { updateRow(); } /** * Invoked when the tree has collapsed. */ public void treeCollapsed(TreeExpansionEvent te) { updateRow(); } /** * Updates the reloadRow and path, this does not genernate a * change event. */ protected void updateRow() { reloadPath = model.getPathLoading(); if (reloadPath != null) { reloadRow = treeTable.getTree().getRowForPath(reloadPath); } } } /** * A renderer that will give an indicator when a cell is being reloaded. */ class IndicatorRenderer extends DefaultTableCellRenderer { /** Makes sure the number of displayed in an internationalized * manner. */ protected NumberFormat formatter; /** Row that is currently being painted. */ protected int lastRow; IndicatorRenderer() { setHorizontalAlignment(JLabel.RIGHT); formatter = NumberFormat.getInstance(); } /** * Invoked as part of DefaultTableCellRenderers implemention. Sets * the text of the label. */ public void setValue(Object value) { setText((value == null) ? "---" : formatter.format(value)); } /** * Returns this. */ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); lastRow = row; return this; } /** * If the row being painted is also being reloaded this will draw * a little indicator. */ public void paint(Graphics g) { if (lastRow == reloadRow) { int width = getWidth(); int height = getHeight(); g.setColor(getBackground()); g.fillRect(0, 0, width, height); g.setColor(getForeground()); int diameter = Math.min(width, height); if (reloadCounter < 5) { g.fillArc((width - diameter) / 2, (height - diameter) / 2, diameter, diameter, 90, -(reloadCounter * 90)); } else { g.fillArc((width - diameter) / 2, (height - diameter) / 2, diameter, diameter, 90, (4 - reloadCounter % 4) * 90); } } else { super.paint(g); } } } public static void main(String[] args) { if (args.length > 0) { for (int counter = args.length - 1; counter >= 0; counter--) { new TreeTableExample2(args[counter]); } } else { String path; try { path = System.getProperty("user.home"); if (path != null) { new TreeTableExample2(path); } } catch (SecurityException se) { path = null; } if (path == null) { System.out.println("Could not determine home directory"); } } } } freehep-swing-2.0.3/src/test/java/org/freehep/swing/treetable/test/MergeSort.java 0000644 0120103 0120103 00000003405 10466735775 031016 0 ustar mascellani mascellani package org.freehep.swing.treetable.test; /** * An implementation of MergeSort, needs to be subclassed to compare the terms. * * @author Scott Violet */ public abstract class MergeSort extends Object { protected Object toSort[]; protected Object swapSpace[]; public void sort(Object array[]) { if(array != null && array.length > 1) { int maxLength; maxLength = array.length; swapSpace = new Object[maxLength]; toSort = array; this.mergeSort(0, maxLength - 1); swapSpace = null; toSort = null; } } public abstract int compareElementsAt(int beginLoc, int endLoc); protected void mergeSort(int begin, int end) { if(begin != end) { int mid; mid = (begin + end) / 2; this.mergeSort(begin, mid); this.mergeSort(mid + 1, end); this.merge(begin, mid, end); } } protected void merge(int begin, int middle, int end) { int firstHalf, secondHalf, count; firstHalf = count = begin; secondHalf = middle + 1; while((firstHalf <= middle) && (secondHalf <= end)) { if(this.compareElementsAt(secondHalf, firstHalf) < 0) swapSpace[count++] = toSort[secondHalf++]; else swapSpace[count++] = toSort[firstHalf++]; } if(firstHalf <= middle) { while(firstHalf <= middle) swapSpace[count++] = toSort[firstHalf++]; } else { while(secondHalf <= end) swapSpace[count++] = toSort[secondHalf++]; } for(count = begin;count <= end;count++) toSort[count] = swapSpace[count]; } } freehep-swing-2.0.3/src/test/java/org/freehep/swing/treetable/test/FileSystemModel2.java 0000644 0120103 0120103 00000045556 10466735775 032253 0 ustar mascellani mascellani package org.freehep.swing.treetable.test; import java.io.File; import java.io.IOException; import java.util.Date; import java.util.Stack; import javax.swing.SwingUtilities; import javax.swing.tree.TreePath; import org.freehep.swing.treetable.AbstractTreeTableModel; import org.freehep.swing.treetable.TreeTableModel; /** * FileSystemModel2 is a TreeTableModel representing a hierarchical file * system.
* This will recursively load all the children from the path it is * created with. The loading is done with the method reloadChildren, and * happens in another thread. The method isReloading can be invoked to check * if there are active threads. The total size of all the files are also * accumulated. *
* By default links are not descended. java.io.File does not have a way * to distinguish links, so a file is assumed to be a link if its canonical * path does not start with its parent path. This may not cover all cases, * but works for the time being. *
Reloading happens such that all the files of the directory are * loaded and immediately available. The background thread then recursively * loads all the files of each of those directories. When each directory has * finished loading all its sub files they are attached and an event is * generated in the event dispatching thread. A more ambitious approach * would be to attach each set of directories as they are loaded and generate * an event. Then, once all the direct descendants of the directory being * reloaded have finished loading, it is resorted based on total size. *
* While you can invoke reloadChildren as many times as you want, care
* should be taken in doing this. You should not invoke reloadChildren
* on a node that is already being reloaded, or going to be reloaded
* (meaning its parent is reloading but it hasn't started reloading
* that directory yet). If this is done odd results may
* happen. FileSystemModel2 does not enforce any policy in this manner,
* and it is up to the user of FileSystemModel2 to ensure it doesn't
* happen.
*
* @version 1.12 05/12/98
* @author Philip Milne
* @author Scott Violet
*/
public class FileSystemModel2 extends AbstractTreeTableModel {
// Names of the columns.
static protected String[] cNames = {"Name", "Size", "Type", "Modified"};
// Types of the columns.
static protected Class[] cTypes = { TreeTableModel.class,
Integer.class, String.class,
Date.class};
// The the returned file length for directories.
public static final Integer ZERO = new Integer(0);
/** An array of MergeSorter sorters, that will sort based on size. */
static Stack sorters = new Stack();
/** True if the receiver is valid, once set to false all Threads
* loading files will stop. */
protected boolean isValid;
/** Node currently being reloaded, this becomes somewhat muddy if
* reloading is happening in multiple threads. */
protected FileNode reloadNode;
/** > 0 indicates reloading some nodes. */
int reloadCount;
/** Returns true if links are to be descended. */
protected boolean descendLinks;
/**
* Returns a MergeSort that can sort on the totalSize of a FileNode.
*/
protected static MergeSort getSizeSorter() {
synchronized(sorters) {
if (sorters.size() == 0) {
return new SizeSorter();
}
return (MergeSort)sorters.pop();
}
}
/**
* Should be invoked when a MergeSort is no longer needed.
*/
protected static void recycleSorter(MergeSort sorter) {
synchronized(sorters) {
sorters.push(sorter);
}
}
/**
* Creates a FileSystemModel2 rooted at File.separator, which is usually
* the root of the file system. This does not load it, you should invoke
* reloadChildren
with the root to start loading.
*/
public FileSystemModel2() {
this(File.separator);
}
/**
* Creates a FileSystemModel2 with the root being rootPath
.
* This does not load it, you should invoke
* reloadChildren
with the root to start loading.
*/
public FileSystemModel2(String rootPath) {
super(null);
isValid = true;
root = new FileNode(new File(rootPath));
}
//
// The TreeModel interface
//
/**
* Returns the number of children of node
.
*/
public int getChildCount(Object node) {
Object[] children = getChildren(node);
return (children == null) ? 0 : children.length;
}
/**
* Returns the child of node
at index i
.
*/
public Object getChild(Object node, int i) {
return getChildren(node)[i];
}
/**
* Returns true if the passed in object represents a leaf, false
* otherwise.
*/
public boolean isLeaf(Object node) {
return ((FileNode)node).isLeaf();
}
//
// The TreeTableNode interface.
//
/**
* Returns the number of columns.
*/
public int getColumnCount() {
return cNames.length;
}
/**
* Returns the name for a particular column.
*/
public String getColumnName(int column) {
return cNames[column];
}
/**
* Returns the class for the particular column.
*/
public Class getColumnClass(int column) {
return cTypes[column];
}
/**
* Returns the value of the particular column.
*/
public Object getValueAt(Object node, int column) {
FileNode fn = (FileNode)node;
try {
switch(column) {
case 0:
return fn.getFile().getName();
case 1:
if (fn.isTotalSizeValid()) {
return new Integer((int)((FileNode)node).totalSize());
}
return null;
case 2:
return fn.isLeaf() ? "File" : "Directory";
case 3:
return fn.lastModified();
}
}
catch (SecurityException se) { }
return null;
}
//
// Some convenience methods.
//
/**
* Reloads the children of the specified node.
*/
public void reloadChildren(Object node) {
FileNode fn = (FileNode)node;
synchronized(this) {
reloadCount++;
}
fn.resetSize();
new Thread(new FileNodeLoader((FileNode)node)).start();
}
/**
* Stops and waits for all threads to finish loading.
*/
public void stopLoading() {
isValid = false;
synchronized(this) {
while (reloadCount > 0) {
try {
wait();
} catch (InterruptedException ie) {}
}
}
isValid = true;
}
/**
* If newValue
is true, links are descended. Odd results
* may happen if you set this while other threads are loading.
*/
public void setDescendsLinks(boolean newValue) {
descendLinks = newValue;
}
/**
* Returns true if links are to be automatically descended.
*/
public boolean getDescendsLinks() {
return descendLinks;
}
/**
* Returns the path node
represents.
*/
public String getPath(Object node) {
return ((FileNode)node).getFile().getPath();
}
/**
* Returns the total size of the receiver.
*/
public long getTotalSize(Object node) {
return ((FileNode)node).totalSize();
}
/**
* Returns true if the receiver is loading any children.
*/
public boolean isReloading() {
return (reloadCount > 0);
}
/**
* Returns the path to the node that is being loaded.
*/
public TreePath getPathLoading() {
FileNode rn = reloadNode;
if (rn != null) {
return new TreePath(rn.getPath());
}
return null;
}
/**
* Returns the node being loaded.
*/
public Object getNodeLoading() {
return reloadNode;
}
protected File getFile(Object node) {
FileNode fileNode = ((FileNode)node);
return fileNode.getFile();
}
protected Object[] getChildren(Object node) {
FileNode fileNode = ((FileNode)node);
return fileNode.getChildren();
}
protected static FileNode[] EMPTY_CHILDREN = new FileNode[0];
// Used to sort the file names.
static private MergeSort fileMS = new MergeSort() {
public int compareElementsAt(int beginLoc, int endLoc) {
return ((String)toSort[beginLoc]).compareTo
((String)toSort[endLoc]);
}
};
/**
* A FileNode is a derivative of the File class - though we delegate to
* the File object rather than subclassing it. It is used to maintain a
* cache of a directory's children and therefore avoid repeated access
* to the underlying file system during rendering.
*/
class FileNode {
/** java.io.File the receiver represents. */
protected File file;
/** Parent FileNode of the receiver. */
private FileNode parent;
/** Children of the receiver. */
protected FileNode[] children;
/** Size of the receiver and all its children. */
protected long totalSize;
/** Valid if the totalSize has finished being calced. */
protected boolean totalSizeValid;
/** Path of the receiver. */
protected String canonicalPath;
/** True if the canonicalPath of this instance does not start with
* the canonical path of the parent. */
protected boolean isLink;
/** Date last modified. */
protected Date lastModified;
protected FileNode(File file) {
this(null, file);
}
protected FileNode(FileNode parent, File file) {
this.parent = parent;
this.file = file;
try {
canonicalPath = file.getCanonicalPath();
}
catch (IOException ioe) {
canonicalPath = "";
}
if (parent != null) {
isLink = !canonicalPath.startsWith(parent.getCanonicalPath());
}
else {
isLink = false;
}
if (isLeaf()) {
totalSize = file.length();
totalSizeValid = true;
}
}
/**
* Returns the date the receiver was last modified.
*/
public Date lastModified() {
if (lastModified == null && file != null) {
lastModified = new Date(file.lastModified());
}
return lastModified;
}
/**
* Returns the the string to be used to display this leaf in the JTree.
*/
public String toString() {
return file.getName();
}
/**
* Returns the java.io.File the receiver represents.
*/
public File getFile() {
return file;
}
/**
* Returns size of the receiver and all its children.
*/
public long totalSize() {
return totalSize;
}
/**
* Returns the parent of the receiver.
*/
public FileNode getParent() {
return parent;
}
/**
* Returns true if the receiver represents a leaf, that is it is
* isn't a directory.
*/
public boolean isLeaf() {
return file.isFile();
}
/**
* Returns true if the total size is valid.
*/
public boolean isTotalSizeValid() {
return totalSizeValid;
}
/**
* Clears the date.
*/
protected void resetLastModified() {
lastModified = null;
}
/**
* Sets the size of the receiver to be 0.
*/
protected void resetSize() {
alterTotalSize(-totalSize);
}
/**
* Loads the children, caching the results in the children
* instance variable.
*/
protected FileNode[] getChildren() {
return children;
}
/**
* Recursively loads all the children of the receiver.
*/
protected void loadChildren(MergeSort sorter) {
totalSize = file.length();
children = createChildren(null);
for (int counter = children.length - 1; counter >= 0; counter--) {
Thread.yield(); // Give the GUI CPU time to draw itself.
if (!children[counter].isLeaf() &&
(descendLinks || !children[counter].isLink())) {
children[counter].loadChildren(sorter);
}
totalSize += children[counter].totalSize();
if (!isValid) {
counter = 0;
}
}
if (isValid) {
if (sorter != null) {
sorter.sort(children);
}
totalSizeValid = true;
}
}
/**
* Loads the children of of the receiver.
*/
protected FileNode[] createChildren(MergeSort sorter) {
FileNode[] retArray = null;
try {
String[] files = file.list();
if(files != null) {
if (sorter != null) {
sorter.sort(files);
}
retArray = new FileNode[files.length];
String path = file.getPath();
for(int i = 0; i < files.length; i++) {
File childFile = new File(path, files[i]);
retArray[i] = new FileNode(this, childFile);
}
}
} catch (SecurityException se) {}
if (retArray == null) {
retArray = EMPTY_CHILDREN;
}
return retArray;
}
/**
* Returns true if the children have been loaded.
*/
protected boolean loadedChildren() {
return (file.isFile() || (children != null));
}
/**
* Gets the path from the root to the receiver.
*/
public FileNode[] getPath() {
return getPathToRoot(this, 0);
}
/**
* Returns the canonical path for the receiver.
*/
public String getCanonicalPath() {
return canonicalPath;
}
/**
* Returns true if the receiver's path does not begin with the
* parent's canonical path.
*/
public boolean isLink() {
return isLink;
}
protected FileNode[] getPathToRoot(FileNode aNode, int depth) {
FileNode[] retNodes;
if(aNode == null) {
if(depth == 0)
return null;
else
retNodes = new FileNode[depth];
}
else {
depth++;
retNodes = getPathToRoot(aNode.getParent(), depth);
retNodes[retNodes.length - depth] = aNode;
}
return retNodes;
}
/**
* Sets the children of the receiver, updates the total size,
* and if generateEvent is true a tree structure changed event
* is created.
*/
protected void setChildren(FileNode[] newChildren,
boolean generateEvent) {
long oldSize = totalSize;
totalSize = file.length();
children = newChildren;
for (int counter = children.length - 1; counter >= 0;
counter--) {
totalSize += children[counter].totalSize();
}
if (generateEvent) {
TreePath path = new TreePath(getPath());
fireTreeStructureChanged(FileSystemModel2.this, path, null,
null);
FileNode parent = getParent();
if (parent != null) {
parent.alterTotalSize(totalSize - oldSize);
}
}
}
protected synchronized void alterTotalSize(long sizeDelta) {
if (sizeDelta != 0 && (parent = getParent()) != null) {
totalSize += sizeDelta;
nodeChanged();
parent.alterTotalSize(sizeDelta);
}
else {
// Need a way to specify the root.
totalSize += sizeDelta;
}
}
/**
* This should only be invoked on the event dispatching thread.
*/
protected synchronized void setTotalSizeValid(boolean newValue) {
if (totalSizeValid != newValue) {
nodeChanged();
totalSizeValid = newValue;
FileNode parent = getParent();
if (parent != null) {
parent.childTotalSizeChanged(this);
}
}
}
/**
* Marks the receivers total size as valid, but does not invoke
* node changed, nor message the parent.
*/
protected synchronized void forceTotalSizeValid() {
totalSizeValid = true;
}
/**
* Invoked when a childs total size has changed.
*/
protected synchronized void childTotalSizeChanged(FileNode child) {
if (totalSizeValid != child.isTotalSizeValid()) {
if (totalSizeValid) {
setTotalSizeValid(false);
}
else {
FileNode[] children = getChildren();
for (int counter = children.length - 1; counter >= 0;
counter--) {
if (!children[counter].isTotalSizeValid()) {
return;
}
}
setTotalSizeValid(true);
}
}
}
/**
* Can be invoked when a node has changed, will create the
* appropriate event.
*/
protected void nodeChanged() {
FileNode parent = getParent();
if (parent != null) {
TreePath path = new TreePath(parent.getPath());
int[] index = { getIndexOfChild(parent, this) };
Object[] children = { this };
fireTreeNodesChanged(FileSystemModel2.this, path, index,
children);
}
}
}
/**
* FileNodeLoader can be used to reload all the children of a
* particular node. It first resets the children of the FileNode
* it is created with, and in its run method will reload all of
* that nodes children. FileNodeLoader may not be running in the event
* dispatching thread. As swing is not thread safe it is important
* that we don't generate events in this thread. SwingUtilities.invokeLater
* is used so that events are generated in the event dispatching thread.
*/
class FileNodeLoader implements Runnable {
/** Node creating children for. */
FileNode node;
/** Sorter. */
MergeSort sizeMS;
FileNodeLoader(FileNode node) {
this.node = node;
node.resetLastModified();
node.setChildren(node.createChildren(fileMS), true);
node.setTotalSizeValid(false);
}
public void run() {
FileNode[] children = node.getChildren();
sizeMS = getSizeSorter();
for (int counter = children.length - 1; counter >= 0; counter--) {
if (!children[counter].isLeaf()) {
reloadNode = children[counter];
loadChildren(children[counter]);
reloadNode = null;
}
if (!isValid) {
counter = 0;
}
}
recycleSorter(sizeMS);
if (isValid) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MergeSort sorter = getSizeSorter();
sorter.sort(node.getChildren());
recycleSorter(sorter);
node.setChildren(node.getChildren(), true);
synchronized(FileSystemModel2.this) {
reloadCount--;
FileSystemModel2.this.notifyAll();
}
}
});
}
else {
synchronized(FileSystemModel2.this) {
reloadCount--;
FileSystemModel2.this.notifyAll();
}
}
}
protected void loadChildren(FileNode node) {
if (!node.isLeaf() && (descendLinks || !node.isLink())) {
final FileNode[] children = node.createChildren(null);
for (int counter = children.length - 1; counter >= 0;
counter--) {
if (!children[counter].isLeaf()) {
if (descendLinks || !children[counter].isLink()) {
children[counter].loadChildren(sizeMS);
}
else {
children[counter].forceTotalSizeValid();
}
}
if (!isValid) {
counter = 0;
}
}
if (isValid) {
final FileNode fn = node;
// Reset the children
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MergeSort sorter = getSizeSorter();
sorter.sort(children);
recycleSorter(sorter);
fn.setChildren(children, true);
fn.setTotalSizeValid(true);
fn.nodeChanged();
}
});
}
}
else {
node.forceTotalSizeValid();
}
}
}
/**
* Sorts the contents, which must be instances of FileNode based on
* totalSize.
*/
static class SizeSorter extends MergeSort {
public int compareElementsAt(int beginLoc, int endLoc) {
long firstSize = ((FileNode)toSort[beginLoc]).totalSize();
long secondSize = ((FileNode)toSort[endLoc]).totalSize();
if (firstSize != secondSize) {
return (int)(secondSize - firstSize);
}
return ((FileNode)toSort[beginLoc]).toString().compareTo
(((FileNode)toSort[endLoc]).toString());
}
}
}
freehep-swing-2.0.3/src/test/java/org/freehep/swing/graphics/ 0000755 0120103 0120103 00000000000 11275634131 025073 5 ustar mascellani mascellani freehep-swing-2.0.3/src/test/java/org/freehep/swing/graphics/test/ 0000755 0120103 0120103 00000000000 11275634131 026052 5 ustar mascellani mascellani freehep-swing-2.0.3/src/test/java/org/freehep/swing/graphics/test/TestGraphicalSelections.java 0000644 0120103 0120103 00000041363 10466735775 033530 0 ustar mascellani mascellani package org.freehep.swing.graphics.test;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
import org.freehep.swing.graphics.GraphicalSelectionEvent;
import org.freehep.swing.graphics.GraphicalSelectionListener;
import org.freehep.swing.graphics.ParallelogramSelectionPanel;
import org.freehep.swing.graphics.PointSelectionEvent;
import org.freehep.swing.graphics.PointSelectionPanel;
import org.freehep.swing.graphics.RectangularSelectionPanel;
import org.freehep.swing.graphics.RegionSelectionEvent;
import org.freehep.swing.graphics.RotatedRectangleSelectionPanel;
import org.freehep.swing.graphics.SquareSelectionPanel;
import org.freehep.swing.graphics.XSkewSelectionPanel;
import org.freehep.swing.graphics.XSliceSelectionPanel;
import org.freehep.swing.graphics.YSkewSelectionPanel;
import org.freehep.swing.graphics.YSliceSelectionPanel;
import org.freehep.swing.layout.StackedLayout;
public class TestGraphicalSelections
extends JFrame {
JLayeredPane mainPanel;
TestPanel drawPanel;
PointSelectionPanel pointSelect;
RectangularSelectionPanel rectSelect;
SquareSelectionPanel squareSelect;
RotatedRectangleSelectionPanel rotateSelect;
XSkewSelectionPanel xskewSelect;
YSkewSelectionPanel yskewSelect;
XSliceSelectionPanel xsliceSelect;
YSliceSelectionPanel ysliceSelect;
ParallelogramSelectionPanel parallelogramSelect;
public TestGraphicalSelections() {
// Title this frame.
super("Graphical Selections Test");
// Make this exit when the close button is clicked.
setDefaultCloseOperation(WindowConstants.
DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {quit();}
});
// Make the main panel container.
mainPanel = new JLayeredPane();
mainPanel.setLayout(new StackedLayout());
// Make the drawing panel.
drawPanel = new TestPanel();
mainPanel.add(drawPanel, new Integer(0));
drawPanel.setPreferredSize(new Dimension(600,400));
// Make the selection panels.
pointSelect = new PointSelectionPanel();
mainPanel.add(pointSelect, new Integer(10));
pointSelect.addGraphicalSelectionListener(drawPanel);
rectSelect = new RectangularSelectionPanel();
mainPanel.add(rectSelect, new Integer(20));
rectSelect.addGraphicalSelectionListener(drawPanel);
squareSelect = new SquareSelectionPanel();
mainPanel.add(squareSelect, new Integer(30));
squareSelect.addGraphicalSelectionListener(drawPanel);
rotateSelect = new RotatedRectangleSelectionPanel();
mainPanel.add(rotateSelect, new Integer(40));
rotateSelect.addGraphicalSelectionListener(drawPanel);
xskewSelect = new XSkewSelectionPanel();
mainPanel.add(xskewSelect, new Integer(50));
xskewSelect.addGraphicalSelectionListener(drawPanel);
yskewSelect = new YSkewSelectionPanel();
mainPanel.add(yskewSelect, new Integer(60));
yskewSelect.addGraphicalSelectionListener(drawPanel);
xsliceSelect = new XSliceSelectionPanel();
mainPanel.add(xsliceSelect, new Integer(70));
xsliceSelect.addGraphicalSelectionListener(drawPanel);
ysliceSelect = new YSliceSelectionPanel();
mainPanel.add(ysliceSelect, new Integer(80));
ysliceSelect.addGraphicalSelectionListener(drawPanel);
parallelogramSelect = new ParallelogramSelectionPanel();
mainPanel.add(parallelogramSelect, new Integer(70));
parallelogramSelect.addGraphicalSelectionListener(drawPanel);
// Make a menu bar and menu.
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("File");
menuBar.add(menu);
// Quit menu item.
JMenuItem item = new JMenuItem("Quit");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
quit();
}});
menu.add(item);
// Add the various types of selections.
menu = new JMenu("Selections");
menuBar.add(menu);
item = new JMenuItem("Point Select");
menu.add(item);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
activePanel(pointSelect);
}});
item = new JMenuItem("Rectangular Selection");
menu.add(item);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
activePanel(rectSelect);
}});
item = new JMenuItem("Square Selection");
menu.add(item);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
activePanel(squareSelect);
}});
item = new JMenuItem("Rot. Rectangle Selection");
menu.add(item);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
activePanel(rotateSelect);
}});
item = new JMenuItem("X-Skew Selection");
menu.add(item);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
activePanel(xskewSelect);
}});
item = new JMenuItem("Y-Skew Selection");
menu.add(item);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
activePanel(yskewSelect);
}});
item = new JMenuItem("X-Slice Selection");
menu.add(item);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
activePanel(xsliceSelect);
}});
item = new JMenuItem("Y-Slice Selection");
menu.add(item);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
activePanel(ysliceSelect);
}});
item = new JMenuItem("Parallelogram Selection");
menu.add(item);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
activePanel(parallelogramSelect);
}});
// Choose what to check.
menu = new JMenu("Options");
menuBar.add(menu);
// Reduce the size.
item = new JMenuItem("Check Selection");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
drawPanel.checkSelection();
}});
menu.add(item);
item = new JMenuItem("Check Transform Of Graphics");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
drawPanel.checkTransform();
}});
menu.add(item);
item = new JMenuItem("Check Transform Of Shapes");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
drawPanel.checkTransformShapes();
}});
menu.add(item);
menu.addSeparator();
item = new JMenuItem("Restore Default Zoom");
menu.add(item);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
drawPanel.defaultTransform();
}});
// Add this to the frame.
setJMenuBar(menuBar);
// Get the content pane.
Container content = this.getContentPane();
content.setLayout(new BorderLayout());
content.add(mainPanel,BorderLayout.CENTER);
//setContentPane(mainPanel);
activePanel(squareSelect);
}
/**
* Just exit the JVM. */
public void quit() {
System.exit(0);
}
public void activePanel(JComponent active) {
pointSelect.setVisible(false);
rectSelect.setVisible(false);
squareSelect.setVisible(false);
rotateSelect.setVisible(false);
xskewSelect.setVisible(false);
yskewSelect.setVisible(false);
xsliceSelect.setVisible(false);
ysliceSelect.setVisible(false);
parallelogramSelect.setVisible(false);
active.setVisible(true);
}
class TestPanel
extends JPanel
implements GraphicalSelectionListener {
/**
* Flag to indicate whether the transform or the selection
* component of the GraphicalSelectionEvent should be
* tested. */
private boolean checkTransform;
/**
* Flag indicating whether to transform the shapes or to set
* the transformation of the Graphics context. */
private boolean transformShapes;
/**
* The transform which should be used for the zooming. */
private AffineTransform transform = new AffineTransform();
/**
* The outline of the selection. For a point, create a small
* diamond surrounding the selected point. */
private Polygon polygon = null;
/**
* List of colors for the six test figures which are drawn. */
private Color[] colors = new Color[6];
/**
* The six test figures. */
Polygon[] bkg = new Polygon[6];
/**
* Temporary array used to create the test
* polygons. (x-coord.) */
int[] xval = new int[4];
/**
* Temporary array used to create the test
* polygons. (y-coord.) */
int[] yval = new int[4];
/**
* GeneralPath used when transforming the shapes directly. */
GeneralPath gp = new GeneralPath();
/**
* Constructor sets up the various geometrical shapes needed
* for this test. */
public TestPanel() {
// Make sure that this component is opaque.
setOpaque(true);
// Start by checking the selections only.
checkTransform = false;
// Start by transforming the shapes.
transformShapes = true;
// Setup the colors for the six geometrical shapes.
colors[0] = Color.red;
colors[1] = Color.green;
colors[2] = Color.blue;
colors[3] = Color.cyan;
colors[4] = Color.magenta;
colors[5] = Color.black;
// A square.
xval[0] = 50;
yval[0] = 50;
xval[1] = 150;
yval[1] = 50;
xval[2] = 150;
yval[2] = 150;
xval[3] = 50;
yval[3] = 150;
bkg[0] = new Polygon(xval,yval,4);
// A rectangle.
xval[0] = 200+50;
yval[0] = 20;
xval[1] = 200+150;
yval[1] = 20;
xval[2] = 200+150;
yval[2] = 180;
xval[3] = 200+50;
yval[3] = 180;
bkg[1] = new Polygon(xval,yval,4);
// A diamond.
xval[0] = 400+100;
yval[0] = 50;
xval[1] = 400+180;
yval[1] = 100;
xval[2] = 400+100;
yval[2] = 150;
xval[3] = 400+20;
yval[3] = 100;
bkg[2] = new Polygon(xval,yval,4);
// A y-skew parallelogram.
xval[0] = 20;
yval[0] = 200+20;
xval[1] = 70;
yval[1] = 200+20;
xval[2] = 180;
yval[2] = 200+180;
xval[3] = 130;
yval[3] = 200+180;
bkg[3] = new Polygon(xval,yval,4);
// An x-skew parallelogram.
xval[0] = 200+20;
yval[0] = 200+20;
xval[1] = 200+20;
yval[1] = 200+70;
xval[2] = 200+180;
yval[2] = 200+180;
xval[3] = 200+180;
yval[3] = 200+130;
bkg[4] = new Polygon(xval,yval,4);
// A rotated rectangle.
xval[0] = 400+160;
yval[0] = 200+20;
xval[1] = 400+180;
yval[1] = 200+40;
xval[2] = 400+40;
yval[2] = 200+180;
xval[3] = 400+20;
yval[3] = 200+160;
bkg[5] = new Polygon(xval,yval,4);
}
/**
* Paint the component. */
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
// Always draw the background on an untransformed graphics
// context.
g2d.setColor(Color.orange);
g2d.fillRect(0,0,getWidth(),getHeight());
// Now draw the shapes on top.
if (transformShapes) {
drawTransformedShapes(g2d);
} else {
drawTransformedGraphics(g2d);
}
}
public void drawTransformedShapes(Graphics2D g2d) {
if (!(checkTransform && transform!=null)) {
transform = new AffineTransform();
}
// Draw all of the standard shapes.
for (int i=0; i<6; i++) {
gp.reset();
gp.append(bkg[i].getPathIterator(transform),false);
g2d.setColor(colors[i]);
g2d.fill(gp);
}
if (polygon!=null && !checkTransform) {
gp.reset();
gp.append(polygon.getPathIterator(transform),false);
g2d.setColor(Color.black);
g2d.draw(gp);
}
}
public void drawTransformedGraphics(Graphics2D g2d) {
if (checkTransform && transform!=null) {
g2d.transform(transform);
} else {
transform = new AffineTransform();
}
// Draw all of the standard shapes.
for (int i=0; i<6; i++) {
g2d.setColor(colors[i]);
g2d.fillPolygon(bkg[i]);
}
if (polygon!=null && !checkTransform) {
g2d.setColor(Color.black);
g2d.drawPolygon(polygon);
}
}
public void checkTransformShapes() {
transformShapes = true;
checkTransform = true;
transform = new AffineTransform();
polygon = null;
repaint();
}
public void checkTransform() {
transformShapes = false;
checkTransform = true;
transform = new AffineTransform();
polygon = null;
repaint();
}
public void checkSelection() {
transformShapes = true;
checkTransform = false;
polygon = null;
transform = new AffineTransform();
repaint();
}
public void defaultTransform() {
transform = new AffineTransform();
repaint();
}
public void graphicalSelectionMade(GraphicalSelectionEvent gsEvent) {
AffineTransform tx = gsEvent.getTransform();
if (transform!=null && tx!=null) {
transform.preConcatenate(tx);
} else {
transform = tx;
}
if (gsEvent instanceof RegionSelectionEvent) {
polygon = (Polygon) gsEvent.getSelection();
} else if (gsEvent instanceof PointSelectionEvent) {
Point p = (Point) gsEvent.getSelection();
xval[0] = p.x;
yval[0] = p.y+10;
xval[1] = p.x+10;
yval[1] = p.y;
xval[2] = p.x;
yval[2] = p.y-10;
xval[3] = p.x-10;
yval[3] = p.y;
polygon = new Polygon(xval,yval,4);
}
repaint();
}
}
public static void main(String[] args) {
// Create a new instance of this class.
TestGraphicalSelections test = new TestGraphicalSelections();
// Layout the component and make it visible.
test.pack();
test.setVisible(true);
test.setLocation(20,20);
test.pack();
}
}
freehep-swing-2.0.3/src/test/java/org/freehep/swing/graphics/test/package.html 0000644 0120103 0120103 00000000050 10470537377 030340 0 ustar mascellani mascellani