package edu.mbl.jif.imaging.nav; import edu.mbl.jif.imaging.nav.dirtree.DirectorySelectionListener; import edu.mbl.jif.imaging.nav.util.FilePathUtils; import edu.mbl.jif.imaging.nav.util.PathWatcherObserver; import edu.mbl.jif.imaging.nav.util.PathWatcher; import edu.mbl.jif.utils.Prefs; import edu.mbl.jif.utils.StaticSwingUtils; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; import java.io.File; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import net.trevize.galatee.GEvent; import net.trevize.galatee.GListener; import net.trevize.galatee.Galatee; import net.trevize.galatee.GalateeFactory; import net.trevize.galatee.GalateeProperties; //import org.apache.commons.io.DirectoryWalker; //import org.apache.commons.io.comparator.NameFileComparator; //import org.apache.commons.io.filefilter.FileFilterUtils; //import org.apache.commons.io.filefilter.HiddenFileFilter; //import org.apache.commons.io.filefilter.IOFileFilter; /** * Creates the image navigation table based on all the settings. * * @author GBH */ public class ImageNavCreator implements DirectorySelectionListener, PathWatcherObserver { private ImageNavigator imgNav; private File dir; // // this is replaced with each change of directory private Galatee currentGalatee; // private boolean recurseSubDirs = false; private int recurseDepth = 8; // ?? private int maxNumFilesBeforeWarning; private boolean firstOnly; // View settings public static final int GRID = 0; public static final int TABLE = 1; private int currentView; private int numColumnsInTableView = 1; private int numColumns = 1; private int numColumnsGridView = 4; private int thumbWidth = 64; private boolean showDescription = true; private int descriptionWidth = 150; private boolean equalizeHisto; // private String currentSelection; // for Path Watching... private PathWatcher pathWatcher; private boolean watchRecursively; private boolean watchingPath; // private FileOpener fileOpener; // public ImageNavCreator(ImageNavigator imgNav, boolean doNotOpen) { this.imgNav = imgNav; pathWatcher = new PathWatcher(this); numColumnsGridView = Prefs.getInt(ImageNavigator.class, "numColsGrid", 4); //thumbWidth = Prefs.getInt(ImageNavigator.class,"thumbWidth", 64); if (!doNotOpen) { fileOpener = new FileOpener(); } } //g.enableSearchFunctionality(); public void setView(int view) { this.currentView = view; // this.setColumnsAndWidth(); // currentGalatee.setView(numColumns, showDescription); } public void setColumnsAndWidth() { int panelWidth = imgNav.thumbsPanel.getWidth(); if (this.currentView == GRID) { numColumns = (int) Math.floor(panelWidth / ((double) thumbWidth + 10)); showDescription = false; } else if (this.currentView == TABLE) { numColumns = numColumnsInTableView; descriptionWidth = panelWidth / numColumnsInTableView - thumbWidth - 20; showDescription = true; } } public void setRecurseSubDirs(boolean recurse) { this.recurseSubDirs = recurse; this.setWatchRecursively(recurse); // if (this.recurseSubDirs) { // GalateeProperties.setSelected_item_background_color("#779438"); // } else { // GalateeProperties.setSelected_item_background_color("#127990"); // } } public void setFirstOnly(boolean selected) { this.firstOnly = selected; } public void setEqualizeHisto(boolean equalizeHisto) { this.equalizeHisto = equalizeHisto; } public void setThumbnailSize(int size) { this.thumbWidth = size; } public int getThumbWidth() { return thumbWidth; } // Galatee.DirectorySelectionListener implementation ===================== @Override /* When a new directory is selected, a new ImageNav is created containing thumbnails for the * images/dataset in that directory and maybe its sub-dirs * This is called by the DirectoryTree */ public void directorySelected(final File directory) { this.dir = directory; System.out.println("directorySelected:" + directory.getPath()); updateImageNav(); if (isWatchingPath()) { pathWatcher.startWatching(this.dir.getAbsolutePath(), isWatchRecursively()); } } // Update/recreate the ImageNav with the current settings public void updateImageNav() { if (dir != null) { new UpdateImageNavThread(dir.getPath(), this.recurseSubDirs).run(); } } class UpdateImageNavThread extends Thread { private final String path; private final boolean recursive; public UpdateImageNavThread(String path, boolean recursive) { this.path = path; this.recursive = recursive; } public void run() { imgNav.setLabelWorking(); //imgNav.showBusyDialog(); setColumnsAndWidth(); currentGalatee = createNewImageNav(path, this.recursive); imgNav.replaceGalatee(currentGalatee); imgNav.setCurrentDirLabel(path); imgNav.setSelectedFileLabel(""); //imgNav.closeBusyDialog(); } } public Galatee createNewImageNav(String path, boolean recursive) { if (currentGalatee != null) { currentGalatee.getImageLoaderThread().terminate(); } Galatee g = GalateeFactory.loadDatasetFromDirectory(path, recursive, recurseDepth, firstOnly, numColumns, thumbWidth, showDescription, descriptionWidth, equalizeHisto); //Galatee g = createGalatee(path + "/*.tif", 88, numColumns, false); g.addGalateeListener(createActionsListener()); addPopUps(g); return g; } // unused... // public Galatee createGalateeWithFileSpec(String path, int size, int numColumns, boolean recursive) { // //loading files and metadata. // Vector<URI> v_uri = new Vector<URI>(); // Vector<Vector<Object>> v_object = new Vector<Vector<Object>>(); // if (!recursive) { // File[] files = new File(path).listFiles(); // if (files != null) { // Arrays.sort(files, NameFileComparator.NAME_INSENSITIVE_COMPARATOR); // for (int i = 0; i < files.length; ++i) { // if (files[i].getName().endsWith(".png") // || files[i].getName().endsWith(".jpg") // || files[i].getName().endsWith(".gif") // || files[i].getName().endsWith(".jpeg") // || files[i].getName().endsWith(".svg") // || files[i].getName().endsWith(".bmp") // || files[i].getName().endsWith(".tif") // || files[i].getName().endsWith(".ppm")) { // // v_uri.add(files[i].toURI()); // Vector<Object> v = new Vector<Object>(); // v.add(files[i].getName()); // v_object.add(v); // } // } // } // } else { // look in all sub-dirs... //// // for Micro-Manager Datasets: //// // for PolScope images, path + "/*retardance*.tif" works using DeepFileSet //// // If a directory contains a //// // only firstOnlyChk one... // // Use the filters to construct the walker // FooDirectoryWalker walker = new FooDirectoryWalker( // HiddenFileFilter.VISIBLE, // FileFilterUtils.suffixFileFilter(".txt")); // // for (File f : new DeepFileSet(path)) { // v_uri.add(f.toURI()); // Vector<Object> v = new Vector<Object>(); // //v.add(f.getName()); // //v.add(f.getPath()); // v.add(f.getParentFile().getName() + "\n" + f.getName()); // v_object.add(v); // // System.out.println(f.getAbsolutePath() + " : " + f.getParent() + " " + f.getName()); // } // } // //} // Galatee g = new Galatee(v_uri, v_object, new Dimension(size, size), 400, numColumns); // g.addGalateeListener(createActionsListener()); // return g; // } // // public class FooDirectoryWalker extends DirectoryWalker { // // public FooDirectoryWalker(IOFileFilter dirFilter, IOFileFilter fileFilter) { // super(dirFilter, fileFilter, -1); // } // } //<editor-fold defaultstate="collapsed" desc="=== Watch Files ======================"> public void setWatchRecursively(boolean watchRecursively) { this.watchRecursively = watchRecursively; } public void setWatchingPath(boolean watchingPath) { this.watchingPath = watchingPath; } private boolean isWatchRecursively() { return this.watchRecursively; } private boolean isWatchingPath() { return this.watchingPath; } // CaresAboutFileChanges implementation ... @Override public void fileCreated(String file) { updateImageNav(); System.out.println("File created: " + file); } @Override public void fileDeleted(String file) { updateImageNav(); System.out.println("File deleted: " + file); } public void terminate() { pathWatcher.stopWatching(); } //</editor-fold> // <editor-fold defaultstate="collapsed" desc=" === Actions ======================================="> // Galatee makes callbacks here on selection or double click // These are called from the image items in the table/grid private GListener createActionsListener() { return new GListener() { // class SystemCommandThread extends Thread { // private SystemCommandHandler2 sch2 = new SystemCommandHandler2(); // private String command; // // public SystemCommandThread(String command) { // this.command = command; // } // public void run() { // String[] commands = new String[1]; // commands[0] = command; // sch2.exec(commands); // } // } @Override public void selectionChanged(GEvent e) { if (e.getSelectedItem() == null) { } else { String dirPath = ImageNavCreator.this.dir.getAbsolutePath(); String thisPath = e.getSelectedItem().getLocalFilepath(); String relativePath = FilePathUtils.getRelativePath(dirPath, thisPath); imgNav.setSelectedFileLabel(relativePath); currentSelection = e.getSelectedItem().getLocalFilepath(); } } @Override public void itemDoubleClicked(GEvent e) { // TODO add image viewer here... System.out.println("item doubleclicked [" + e.getSelectedItem().getLocalFilepath() + "]"); processDoubleClick(e.getSelectedItem().getLocalFilepath()); } }; } // On double-click, open image or notify FileChoosenListeners private void processDoubleClick(String localFilepath) { imgNav.notifyFileChoosenListeners(new File(localFilepath)); if (fileOpener != null) { fileOpener.openFile(localFilepath); } } // Popup Menu for images in the table or grid (in the Galatee) public void addPopUps(Galatee g) { // Add popup menu options... JPopupMenu popup_menu = new JPopupMenu(); JMenuItem item; item = new JMenuItem("Title"); item.setEnabled(false); popup_menu.add(item); popup_menu.addSeparator(); item = new JMenuItem("Open with..."); popup_menu.add(item); item = new JMenuItem(openTreeAtDirectory); popup_menu.add(item); popup_menu.addSeparator(); item = new JMenuItem(copyPathToClipboard); popup_menu.add(item); g.setPopup_menu(popup_menu); } Action openTreeAtDirectory = new AbstractAction("OpenDirectory") { // TODO -- This is very slow... // Open the Directory tree at the directory of the selected file @Override public void actionPerformed(ActionEvent e) { if (currentSelection == null) { return; } System.out.println("currentSelection: " + currentSelection); File f = new File(currentSelection); String dirPath = f.getParent(); System.out.println("parent: " + dirPath); final String dirPathFixed = FilePathUtils.forceForwardSlashes(dirPath); StaticSwingUtils.dispatchToEDT(new Runnable() { public void run() { imgNav.getDirTree().setStartIn(dirPathFixed); } }); } }; Action copyPathToClipboard = new AbstractAction("Copy Path") { @Override public void actionPerformed(ActionEvent e) { if (currentSelection == null) { return; } StringSelection stringSelection = new StringSelection(currentSelection); Clipboard clpbrd = Toolkit.getDefaultToolkit().getSystemClipboard(); clpbrd.setContents(stringSelection, null); } }; // </editor-fold> // }