diff --git a/src/com/bytezone/diskbrowser/disk/AppleDisk.java b/src/com/bytezone/diskbrowser/disk/AppleDisk.java index d8bfb70..cf30d79 100755 --- a/src/com/bytezone/diskbrowser/disk/AppleDisk.java +++ b/src/com/bytezone/diskbrowser/disk/AppleDisk.java @@ -20,7 +20,6 @@ import com.bytezone.diskbrowser.utilities.HexFormatter; public class AppleDisk implements Disk { - private static final String newLine = String.format ("%n"); private static final int MAX_INTERLEAVE = 3; private static final int SECTOR_SIZE = 256; private static final int BLOCK_SIZE = 512; @@ -126,13 +125,9 @@ public class AppleDisk implements Disk System.out.printf ("Blocks : %,d%n", blocks); } - // int format = buffer[12] & 0xFF; - // if (blocks == 0 && format == 1) - // { this.blocks = diskData / 4096 * 8; // reduce blocks to a multiple of 8 if (debug) System.out.printf ("Blocks : %,d%n", blocks); - // } this.sectorSize = 512; this.trackSize = 8 * sectorSize; @@ -171,19 +166,6 @@ public class AppleDisk implements Disk } } - if (false) - { - System.out.println (); - System.out.printf ("File name : %s%n", file.getName ()); - System.out.printf ("File size : %,d%n", file.length ()); - System.out.println ("Tracks : " + tracks); - System.out.println ("Sectors : " + sectors); - System.out.println ("Blocks : " + blocks); - System.out.println ("Sector size : " + sectorSize); - System.out.println ("Track size : " + trackSize); - System.out.println (); - } - if (sectorSize != 256 && sectorSize != 512) throw new FileFormatException ("Invalid sector size : " + sectorSize); @@ -601,13 +583,15 @@ public class AppleDisk implements Disk { StringBuilder text = new StringBuilder (); - text.append ("Path............ " + file.getAbsolutePath () + newLine); + text.append (String.format ("Path............ %s%n", file.getAbsolutePath ())); + text.append (String.format ("File name....... %s%n", file.getName ())); text.append (String.format ("File size....... %,d%n", file.length ())); - text.append ("Tracks.......... " + tracks + newLine); - text.append ("Sectors......... " + sectors + newLine); + text.append (String.format ("Tracks.......... %d%n", tracks)); + text.append (String.format ("Sectors......... %d%n", sectors)); text.append (String.format ("Blocks.......... %,d%n", blocks)); - text.append ("Sector size..... " + sectorSize + newLine); - text.append ("Interleave...... " + interleave + newLine); + text.append (String.format ("Track size...... %,d%n", trackSize)); + text.append (String.format ("Sector size..... %d%n", sectorSize)); + text.append (String.format ("Interleave...... %d", interleave)); return text.toString (); } diff --git a/src/com/bytezone/diskbrowser/disk/DiskFactory.java b/src/com/bytezone/diskbrowser/disk/DiskFactory.java index 727cebc..5e26521 100755 --- a/src/com/bytezone/diskbrowser/disk/DiskFactory.java +++ b/src/com/bytezone/diskbrowser/disk/DiskFactory.java @@ -288,7 +288,6 @@ public class DiskFactory return disk; } - // private static DosDisk checkDos (File file) private static DosDisk checkDos (AppleDisk disk) { if (debug) @@ -296,8 +295,6 @@ public class DiskFactory try { - // int sectors = file.length () == 143360 ? 16 : 13; - // AppleDisk disk = new AppleDisk (file, 35, sectors); if (DosDisk.isCorrectFormat (disk)) return new DosDisk (disk); } @@ -309,7 +306,6 @@ public class DiskFactory return null; } - // private static ProdosDisk checkProdos (File file) private static ProdosDisk checkProdos (AppleDisk disk) { if (debug) @@ -317,7 +313,6 @@ public class DiskFactory try { - // AppleDisk disk = new AppleDisk (file, 35, 8); if (ProdosDisk.isCorrectFormat (disk)) return new ProdosDisk (disk); } @@ -348,14 +343,6 @@ public class DiskFactory return null; } - // assumes a track is 4096 bytes - // if ((file.length () % 4096) != 0) - // { - // if (debug) - // System.out.printf ("file length not divisible by 4096 : %d%n%n", file.length ()); - // return null; - // } - try { // truncate the file if necessary @@ -372,7 +359,6 @@ public class DiskFactory } catch (Exception e) { - // e.printStackTrace (); System.out.println (e); } @@ -402,13 +388,11 @@ public class DiskFactory return null; } - // private static FormattedDisk checkPascalDisk (File file) private static FormattedDisk checkPascalDisk (AppleDisk disk) { if (debug) System.out.println ("Checking Pascal disk"); - // AppleDisk disk = new AppleDisk (file, 35, 8); File file = disk.getFile (); if (!PascalDisk.isCorrectFormat (disk, debug)) @@ -469,9 +453,8 @@ public class DiskFactory { String old = new String (c + "." + suffix); String rep = new String ((char) (c + i - 1) + "." + suffix); - // System.out.printf ("[%s] [%s]%n", old, rep); + File f = new File (fileName.replace (old, rep)); - // System.out.println (f); if (!f.exists () || !f.isFile ()) return false; @@ -483,37 +466,31 @@ public class DiskFactory return true; } - // private static V2dDisk checkV2DDisk (File file) - // { - // // System.out.println ("possible V2D disk"); - // new V2dDisk (file); - // - // return null; - // } - - // private static InfocomDisk checkInfocomDisk (File file) private static InfocomDisk checkInfocomDisk (AppleDisk disk) { if (debug) System.out.println ("Checking Infocom disk"); - // AppleDisk disk = new AppleDisk (file, 35, 16); + if (InfocomDisk.isCorrectFormat (disk)) return new InfocomDisk (disk); + if (debug) System.out.println ("Not an InfocomDisk disk"); + return null; } - // private static CPMDisk checkCPMDisk (File file) private static CPMDisk checkCPMDisk (AppleDisk disk) { if (debug) System.out.println ("Checking CPM disk"); - // AppleDisk disk = new AppleDisk (file, 35, 16); + if (CPMDisk.isCorrectFormat (disk)) return new CPMDisk (disk); + if (debug) System.out.println ("Not a CPM disk"); + return null; } } \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/gui/DiskDetails.java b/src/com/bytezone/diskbrowser/duplicates/DiskDetails.java similarity index 60% rename from src/com/bytezone/diskbrowser/gui/DiskDetails.java rename to src/com/bytezone/diskbrowser/duplicates/DiskDetails.java index efeefad..3d6cc5a 100644 --- a/src/com/bytezone/diskbrowser/gui/DiskDetails.java +++ b/src/com/bytezone/diskbrowser/duplicates/DiskDetails.java @@ -1,14 +1,14 @@ -package com.bytezone.diskbrowser.gui; +package com.bytezone.diskbrowser.duplicates; import java.io.File; import com.bytezone.common.ComputeCRC32; -class DiskDetails +public class DiskDetails { private final File file; private long checksum = -1; - boolean duplicate; + private boolean duplicate; public DiskDetails (File file) { @@ -16,6 +16,16 @@ class DiskDetails duplicate = false; } + public boolean isDuplicate () + { + return duplicate; + } + + public void setDuplicate (boolean value) + { + duplicate = value; + } + public String getAbsolutePath () { return file.getAbsolutePath (); @@ -30,13 +40,14 @@ class DiskDetails public boolean delete () { - return file.delete (); + // return file.delete (); + return false; } @Override public String toString () { return String.format ("%s (%s)", file.getAbsolutePath (), - duplicate ? "duplicate" : "OK"); + duplicate ? "duplicate" : "OK"); } } \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/duplicates/DuplicateHandler.java b/src/com/bytezone/diskbrowser/duplicates/DuplicateHandler.java new file mode 100644 index 0000000..62e5156 --- /dev/null +++ b/src/com/bytezone/diskbrowser/duplicates/DuplicateHandler.java @@ -0,0 +1,141 @@ +package com.bytezone.diskbrowser.duplicates; + +import java.io.File; +import java.util.*; +import java.util.zip.CRC32; +import java.util.zip.Checksum; + +import com.bytezone.diskbrowser.disk.AppleDisk; +import com.bytezone.diskbrowser.disk.Disk; +import com.bytezone.diskbrowser.gui.FileComparator; +import com.bytezone.diskbrowser.utilities.Utility; + +public class DuplicateHandler +{ + private static String spaces = " "; + private static final FileComparator fileComparator = new FileComparator (); + private static final int MAX_NAME_WIDTH = 34; + private static final String FORMAT = "%-" + MAX_NAME_WIDTH + "s %,10d%n"; + + private final File rootFolder; + private int totalDisks; + private int totalFolders; + + // total files for each suffix + private final Map typeList = new TreeMap (); + + // list of unique disk names -> List of File duplicates + final Map> duplicateDisks = + new TreeMap> (); + + // list of unique disk names -> File + private final Map diskNames = new HashMap (); + + // list of checksum -> File + final Map> dosMap = new TreeMap> (); + + public DuplicateHandler (File rootFolder) + { + this.rootFolder = rootFolder; + countDisks (); + } + + void countDisks () + { + traverse (rootFolder, 0); + + System.out.printf ("%nFolders ..... %,5d%n", totalFolders); + System.out.printf ("Disks ....... %,5d%n%n", totalDisks); + + int grandTotal = 0; + for (String key : typeList.keySet ()) + { + int typeTotal = typeList.get (key); + grandTotal += typeTotal; + System.out.printf ("%13.13s %,6d%n", key + " ...........", typeTotal); + } + System.out.printf ("%nTotal ....... %,6d%n%n", grandTotal); + } + + private void traverse (File directory, int depth) + { + File[] files = directory.listFiles (); + if (files == null || files.length == 0) + { + System.out.println ("Empty folder : " + directory.getAbsolutePath ()); + return; + } + + Arrays.sort (files, fileComparator); + + System.out.printf ("%nFolder: %s%n%n", + directory.getAbsolutePath ().substring (rootFolder.getAbsolutePath ().length ())); + + for (File file : files) + { + if (file.isDirectory ()) + { + ++totalFolders; + traverse (file, depth + 1); + } + else if (Utility.validFileType (file.getName ())) + { + if (file.getName ().endsWith (".gz") && !file.getName ().endsWith ("dsk.gz")) + continue; + + ++totalDisks; + + String name = file.getName (); + int nameLength = name.length (); + if (nameLength > MAX_NAME_WIDTH) + name = name.substring (0, 15) + "..." + + name.substring (nameLength - MAX_NAME_WIDTH + 18); + + System.out.printf (FORMAT, name, file.length ()); + } + } + } + + private void checksumDos (File file) + { + if (file.length () != 143360 || file.getAbsolutePath ().contains ("/ZDisks/")) + return; + + Disk disk = new AppleDisk (file, 35, 16); + byte[] buffer = disk.readSector (0, 0); + + Checksum checksum = new CRC32 (); + checksum.update (buffer, 0, buffer.length); + long cs = checksum.getValue (); + List files = dosMap.get (cs); + if (files == null) + { + files = new ArrayList (); + dosMap.put (cs, files); + } + files.add (file); + } + + private void checkDuplicates (File file) + { + if (diskNames.containsKey (file.getName ())) + { + List diskList = duplicateDisks.get (file.getName ()); + if (diskList == null) + { + diskList = new ArrayList (); + duplicateDisks.put (file.getName (), diskList); + diskList.add (new DiskDetails (diskNames.get (file.getName ())));// add original + } + diskList.add (new DiskDetails (file)); // add the duplicate + } + else + diskNames.put (file.getName (), file); + } + + public static void main (String[] args) + { + DuplicateHandler dh = new DuplicateHandler ( + new File ("/Users/denismolony/Apple II stuff/AppleDisk Images II/apple disks")); + } +} \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/gui/CatalogPanel.java b/src/com/bytezone/diskbrowser/gui/CatalogPanel.java index af079d5..10c9eaa 100755 --- a/src/com/bytezone/diskbrowser/gui/CatalogPanel.java +++ b/src/com/bytezone/diskbrowser/gui/CatalogPanel.java @@ -33,11 +33,11 @@ import com.bytezone.diskbrowser.disk.DualDosDisk; import com.bytezone.diskbrowser.disk.FormattedDisk; import com.bytezone.diskbrowser.gui.RedoHandler.RedoEvent; import com.bytezone.diskbrowser.gui.RedoHandler.RedoListener; +import com.bytezone.diskbrowser.gui.RootDirectoryAction.RootDirectoryListener; import com.bytezone.diskbrowser.gui.TreeBuilder.FileNode; -class CatalogPanel extends JTabbedPane - implements RedoListener, SectorSelectionListener, QuitListener, FontChangeListener -// PreferenceChangeListener +class CatalogPanel extends JTabbedPane implements RedoListener, SectorSelectionListener, + QuitListener, FontChangeListener, RootDirectoryListener { private static final String prefsLastDiskUsed = "Last disk used"; private static final String prefsLastDosUsed = "Last dos used"; @@ -51,13 +51,13 @@ class CatalogPanel extends JTabbedPane private final DocumentCreatorFactory lister; private final DiskAndFileSelector selector = new DiskAndFileSelector (); private final RedoHandler redoHandler; - private DuplicateAction duplicateAction; // this sux private CloseTabAction closeTabAction; + private File rootDirectoryFile; public CatalogPanel (MenuHandler mh, RedoHandler redoHandler, Preferences prefs) { // String catalogFontName = - // prefs.get (PreferencesDialog.prefsCatalogFont, PreferencesDialog.defaultFontName); + // prefs.get (PreferencesDialog.prefsCatalogFont, PreferencesDialog.defaultFontName); // int catalogFontSize = // prefs.getInt (PreferencesDialog.prefsCatalogFontSize, // PreferencesDialog.defaultFontSize); @@ -75,11 +75,16 @@ class CatalogPanel extends JTabbedPane addChangeListener (new TabChangeListener ()); } + File getRootDirectory () + { + return rootDirectoryFile; + } + private void createTabs (Preferences prefs) { String rootDirectory = prefs.get (prefsRootDirectory, ""); - File rootDirectoryFile = new File (rootDirectory); + rootDirectoryFile = new File (rootDirectory); if (!rootDirectoryFile.exists () || !rootDirectoryFile.isDirectory ()) { System.out.println ("No root directory"); @@ -113,11 +118,7 @@ class CatalogPanel extends JTabbedPane else System.out.println ("no disk selected"); - fileTab = - new FileSystemTab (rootDirectoryFile, selector, redoHandler, font, diskEvent); - fileTab.addTreeMouseListener (new MouseListener ()); // listen for disk selection - lister.catalogLister.setNode (fileTab.getRootNode ()); - insertTab ("Disk Tree", null, fileTab, "Display Apple disks", 0); + insertFileSystemTab (rootDirectoryFile, diskEvent); if (diskEvent != null) { @@ -154,6 +155,27 @@ class CatalogPanel extends JTabbedPane } } + @Override + public void rootDirectoryChanged (File root) + { + // is the user replacing an existing root folder? + if (fileTab != null) + removeTabAt (0); + + insertFileSystemTab (root, null); + setSelectedIndex (0); + } + + private void insertFileSystemTab (File root, DiskSelectedEvent diskEvent) + { + rootDirectoryFile = root; + fileTab = + new FileSystemTab (rootDirectoryFile, selector, redoHandler, font, diskEvent); + fileTab.addTreeMouseListener (new MouseListener ()); // listen for disk selection + lister.catalogLister.setNode (fileTab.getRootNode ()); + insertTab ("Disk Tree", null, fileTab, "Display Apple disks", 0); + } + public void activate () { if (fileTab == null) @@ -168,45 +190,18 @@ class CatalogPanel extends JTabbedPane setSelectedIndex (0); } - void setDuplicateAction (DuplicateAction action) - { - this.duplicateAction = action; - if (fileTab != null && fileTab.rootFolder != null) - action.setDuplicates (fileTab.rootFolder, fileTab.duplicateDisks); - } + // void setDuplicateAction (DuplicateAction action) + // { + // this.duplicateAction = action; + // if (fileTab != null && fileTab.rootFolder != null) + // action.setDuplicates (fileTab.rootFolder, fileTab.duplicateDisks); + // } void setCloseTabAction (CloseTabAction action) { this.closeTabAction = action; } - // called by RootDirectoryAction - public void changeRootPanel (File root) - { - // try - // { - // This might throw a NoDisksFoundException - FileSystemTab newFileTab = new FileSystemTab (root, selector, redoHandler, font); - - // is the user replacing an existing root folder? - if (fileTab != null) - removeTabAt (0); - - fileTab = newFileTab; - fileTab.addTreeMouseListener (new MouseListener ()); // listen for disk selection - lister.catalogLister.setNode (fileTab.getRootNode ()); - - insertTab ("Disk Tree", null, fileTab, null, 0); - setSelectedIndex (0); - duplicateAction.setDuplicates (fileTab.rootFolder, fileTab.duplicateDisks); - // } - // catch (NoDisksFoundException e) - // { - // JOptionPane.showMessageDialog (null, "Folder " + root.getAbsolutePath () - // + " has no valid disk images.", "Bad folder", JOptionPane.ERROR_MESSAGE); - // } - } - // called after a double-click in the fileTab public void addDiskPanel (FormattedDisk disk, String lastFileUsed, boolean activate) { diff --git a/src/com/bytezone/diskbrowser/gui/DiskBrowser.java b/src/com/bytezone/diskbrowser/gui/DiskBrowser.java index 73c9eff..94a91f5 100755 --- a/src/com/bytezone/diskbrowser/gui/DiskBrowser.java +++ b/src/com/bytezone/diskbrowser/gui/DiskBrowser.java @@ -53,8 +53,12 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi addPanel (diskLayoutPanel, "Disk layout", BorderLayout.EAST); // create actions + DuplicateAction duplicateAction = new DuplicateAction (); RootDirectoryAction rootDirectoryAction = - new RootDirectoryAction (null, catalogPanel); + new RootDirectoryAction (catalogPanel.getRootDirectory ()); + rootDirectoryAction.addListener (catalogPanel); + rootDirectoryAction.addListener (duplicateAction); + RefreshTreeAction refreshTreeAction = new RefreshTreeAction (catalogPanel); // PreferencesAction preferencesAction = new PreferencesAction (this, prefs); AbstractAction print = new PrintAction (dataPanel); @@ -64,7 +68,6 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi HideLayoutAction hideLayoutAction = new HideLayoutAction (this, layoutBorderPanel); ShowFreeSectorsAction showFreeAction = new ShowFreeSectorsAction (menuHandler, diskLayoutPanel); - DuplicateAction duplicateAction = new DuplicateAction (); CloseTabAction closeTabAction = new CloseTabAction (catalogPanel); // add action buttons to toolbar @@ -121,7 +124,7 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi quitAction.addQuitListener (diskLayoutPanel); quitAction.addQuitListener (this); - catalogPanel.setDuplicateAction (duplicateAction); + // catalogPanel.setDuplicateAction (duplicateAction); catalogPanel.setCloseTabAction (closeTabAction); pack (); diff --git a/src/com/bytezone/diskbrowser/gui/DuplicateAction.java b/src/com/bytezone/diskbrowser/gui/DuplicateAction.java index 582e866..a8c298a 100644 --- a/src/com/bytezone/diskbrowser/gui/DuplicateAction.java +++ b/src/com/bytezone/diskbrowser/gui/DuplicateAction.java @@ -15,9 +15,11 @@ import java.util.Map; import javax.swing.*; import com.bytezone.common.DefaultAction; +import com.bytezone.diskbrowser.duplicates.DiskDetails; +import com.bytezone.diskbrowser.gui.RootDirectoryAction.RootDirectoryListener; import com.bytezone.input.SpringUtilities; -public class DuplicateAction extends DefaultAction +public class DuplicateAction extends DefaultAction implements RootDirectoryListener { Map> duplicateDisks; int rootFolderLength; @@ -27,18 +29,25 @@ public class DuplicateAction extends DefaultAction public DuplicateAction () { super ("Check for duplicates...", "Check for duplicate disks", - "/com/bytezone/diskbrowser/icons/"); + "/com/bytezone/diskbrowser/icons/"); setIcon (Action.SMALL_ICON, "save_delete_16.png"); setIcon (Action.LARGE_ICON_KEY, "save_delete_32.png"); } - public void setDuplicates (File rootFolder, Map> duplicateDisks) + // public void setDuplicates (File rootFolder, + // Map> duplicateDisks) + // { + // this.duplicateDisks = duplicateDisks; + // this.rootFolderLength = rootFolder.getAbsolutePath ().length (); + // setEnabled (duplicateDisks.size () > 0); + // } + + @Override + public void rootDirectoryChanged (File newRootDirectory) { - this.duplicateDisks = duplicateDisks; - this.rootFolderLength = rootFolder.getAbsolutePath ().length (); - this.rootFolder = rootFolder; - setEnabled (duplicateDisks.size () > 0); + this.rootFolder = newRootDirectory; + System.out.println ("gotcha"); } @Override @@ -72,7 +81,8 @@ public class DuplicateAction extends DefaultAction JPanel mainPanel = new JPanel (); List disksSelected = new ArrayList (); - List duplicatePanels = new ArrayList (); + List duplicatePanels = + new ArrayList (); public DuplicateWindow () { @@ -82,8 +92,8 @@ public class DuplicateAction extends DefaultAction mainPanel.setLayout (new BoxLayout (mainPanel, BoxLayout.PAGE_AXIS)); - JScrollPane sp = - new JScrollPane (mainPanel, VERTICAL_SCROLLBAR_ALWAYS, HORIZONTAL_SCROLLBAR_NEVER); + JScrollPane sp = new JScrollPane (mainPanel, VERTICAL_SCROLLBAR_ALWAYS, + HORIZONTAL_SCROLLBAR_NEVER); sp.getVerticalScrollBar ().setUnitIncrement (100); add (sp, BorderLayout.CENTER); @@ -109,7 +119,7 @@ public class DuplicateAction extends DefaultAction int count = 0; for (JCheckBox cb : dp.checkBoxes) { - if (count > 0 && dp.duplicateDisks.get (count).duplicate) + if (count > 0 && dp.duplicateDisks.get (count).isDuplicate ()) if (!cb.isSelected ()) { cb.setSelected (true); // doesn't fire the actionListener! @@ -189,9 +199,8 @@ public class DuplicateAction extends DefaultAction public synchronized void addResult (List duplicateDisks) { // create panel and add it to the window - DuplicatePanel dp = - new DuplicatePanel (duplicateDisks, folderNameLength, disksSelected, buttonDelete, - buttonClear); + DuplicatePanel dp = new DuplicatePanel (duplicateDisks, folderNameLength, + disksSelected, buttonDelete, buttonClear); mainPanel.add (dp); duplicatePanels.add (dp); @@ -213,7 +222,7 @@ public class DuplicateAction extends DefaultAction List duplicateDisks; public DuplicatePanel (List duplicateDisks, int folderNameLength, - List disksSelected, JButton deleteButton, JButton clearButton) + List disksSelected, JButton deleteButton, JButton clearButton) { this.duplicateDisks = duplicateDisks; setLayout (new SpringLayout ()); @@ -225,23 +234,23 @@ public class DuplicateAction extends DefaultAction JCheckBox cb = new JCheckBox (); checkBoxes.add (cb); - cb.addActionListener (new CheckBoxActionListener (dd, disksSelected, deleteButton, - clearButton)); + cb.addActionListener ( + new CheckBoxActionListener (dd, disksSelected, deleteButton, clearButton)); add (cb); if (++count == 1) add (new JLabel ("Source disk")); else { - String text = dd.duplicate ? "Duplicate" : "OK"; + String text = dd.isDuplicate () ? "Duplicate" : "OK"; add (new JLabel (text)); } - String checksum = - dd.duplicate || count == 1 ? "" : " (checksum = " + dd.getChecksum () + ")"; + String checksum = dd.isDuplicate () || count == 1 ? "" + : " (checksum = " + dd.getChecksum () + ")"; add (new JLabel (dd.getAbsolutePath ().substring (folderNameLength) + checksum)); } SpringUtilities.makeCompactGrid (this, duplicateDisks.size (), 3, //rows, cols - 10, 0, //initX, initY - 10, 0); //xPad, yPad + 10, 0, //initX, initY + 10, 0); //xPad, yPad } } @@ -252,8 +261,8 @@ public class DuplicateAction extends DefaultAction JButton deleteButton; JButton clearButton; - public CheckBoxActionListener (DiskDetails diskDetails, List disksSelected, - JButton deleteButton, JButton clearButton) + public CheckBoxActionListener (DiskDetails diskDetails, + List disksSelected, JButton deleteButton, JButton clearButton) { this.diskDetails = diskDetails; this.disksSelected = disksSelected; @@ -306,7 +315,7 @@ public class DuplicateAction extends DefaultAction if (firstChecksum < 0) firstChecksum = dd.getChecksum (); else - dd.duplicate = (dd.getChecksum () == firstChecksum); + dd.setDuplicate (dd.getChecksum () == firstChecksum); } return duplicateDisks; } diff --git a/src/com/bytezone/diskbrowser/gui/FileComparator.java b/src/com/bytezone/diskbrowser/gui/FileComparator.java new file mode 100644 index 0000000..6859dfe --- /dev/null +++ b/src/com/bytezone/diskbrowser/gui/FileComparator.java @@ -0,0 +1,22 @@ +package com.bytezone.diskbrowser.gui; + +import java.io.File; +import java.util.Comparator; + +public class FileComparator implements Comparator +{ + + @Override + public int compare (File thisFile, File thatFile) + { + boolean thisFileIsDirectory = thisFile.isDirectory (); + boolean thatFileIsDirectory = thatFile.isDirectory (); + + if (thisFileIsDirectory && !thatFileIsDirectory) + return 1; + if (!thisFileIsDirectory && thatFileIsDirectory) + return -1; + + return thisFile.getName ().compareToIgnoreCase (thatFile.getName ()); + } +} \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/gui/FileSystemTab.java b/src/com/bytezone/diskbrowser/gui/FileSystemTab.java index 5e1de1b..f308eda 100755 --- a/src/com/bytezone/diskbrowser/gui/FileSystemTab.java +++ b/src/com/bytezone/diskbrowser/gui/FileSystemTab.java @@ -10,8 +10,6 @@ package com.bytezone.diskbrowser.gui; import java.awt.Font; import java.io.File; import java.util.Enumeration; -import java.util.List; -import java.util.Map; import javax.swing.JTree; import javax.swing.event.TreeExpansionEvent; @@ -30,20 +28,18 @@ import com.bytezone.diskbrowser.gui.TreeBuilder.FileNode; class FileSystemTab extends AbstractTab { File rootFolder; - Map> duplicateDisks; + // Map> duplicateDisks; public FileSystemTab (File folder, DiskAndFileSelector selector, RedoHandler navMan, - Font font, DiskSelectedEvent diskEvent) // throws NoDisksFoundException + Font font, DiskSelectedEvent diskEvent) { super (navMan, selector, font); this.rootFolder = folder; TreeBuilder tb = new TreeBuilder (folder); - // if (tb.totalDisks == 0) - // throw new NoDisksFoundException (); - duplicateDisks = tb.duplicateDisks; - setTree (tb.tree); + // duplicateDisks = tb.duplicateDisks; + setTree (tb.getTree ()); setSelectionListener (tree); if (diskEvent == null) @@ -62,36 +58,35 @@ class FileSystemTab extends AbstractTab System.out.println ("No disk event"); // temporary code while I sort out the DOS checksum feature - if (tb.dosMap.keySet ().size () > 0) - { - System.out.printf ("Unique DOSs : %4d%n", tb.dosMap.keySet ().size ()); - long lastKey = -1; - int beginIndex = rootFolder.getAbsolutePath ().length (); - for (Long key : tb.dosMap.keySet ()) - { - if (key != lastKey) - { - lastKey = key; - System.out.printf ("%,14d (%d)%n", key, tb.dosMap.get (key).size ()); - } - for (File file : tb.dosMap.get (key)) - System.out.printf (" %s%n", - file.getAbsolutePath ().substring (beginIndex)); - } - } + // if (tb.dosMap.keySet ().size () > 0) + // { + // System.out.printf ("Unique DOSs : %4d%n", tb.dosMap.keySet ().size ()); + // long lastKey = -1; + // int beginIndex = rootFolder.getAbsolutePath ().length (); + // for (Long key : tb.dosMap.keySet ()) + // { + // if (key != lastKey) + // { + // lastKey = key; + // System.out.printf ("%,14d (%d)%n", key, tb.dosMap.get (key).size ()); + // } + // for (File file : tb.dosMap.get (key)) + // System.out.printf (" %s%n", + // file.getAbsolutePath ().substring (beginIndex)); + // } + // } } public FileSystemTab (File folder, DiskAndFileSelector selector, RedoHandler navMan, Font font) - // throws NoDisksFoundException { - this (folder, selector, navMan, font, null); // default to first available disk + this (folder, selector, navMan, font, null); // default to first available disk } @Override public void activate () { - tree.setSelectionPath (null); // turn off any current selection to force an event + tree.setSelectionPath (null); // turn off any current selection to force an event redoHandler.setCurrentData (redoData); } @@ -101,7 +96,7 @@ class FileSystemTab extends AbstractTab { String currentDiskName = ((FileNode) getSelectedObject ()).file.getAbsolutePath (); TreeBuilder tb = new TreeBuilder (rootFolder); - setTree (tb.tree); + setTree (tb.getTree ()); if (currentDiskName != null) showNode (findNode (currentDiskName)); setSelectionListener (tree); diff --git a/src/com/bytezone/diskbrowser/gui/RootDirectoryAction.java b/src/com/bytezone/diskbrowser/gui/RootDirectoryAction.java index 830813a..4b12f8e 100755 --- a/src/com/bytezone/diskbrowser/gui/RootDirectoryAction.java +++ b/src/com/bytezone/diskbrowser/gui/RootDirectoryAction.java @@ -3,6 +3,8 @@ package com.bytezone.diskbrowser.gui; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.io.File; +import java.util.ArrayList; +import java.util.List; import javax.swing.Action; import javax.swing.JFileChooser; @@ -13,20 +15,21 @@ import com.bytezone.common.Platform; class RootDirectoryAction extends DefaultAction { - File rootDirectory; - CatalogPanel catalogPanel; + private File rootDirectory; + private final List listeners = + new ArrayList (); - public RootDirectoryAction (File rootDirectory, CatalogPanel catalogPanel) + public RootDirectoryAction (File rootDirectory) { super ("Set HOME folder...", "Defines root folder where the disk images are kept", - "/com/bytezone/diskbrowser/icons/"); + "/com/bytezone/diskbrowser/icons/"); putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt H")); putValue (Action.MNEMONIC_KEY, KeyEvent.VK_H); - this.rootDirectory = rootDirectory; - this.catalogPanel = catalogPanel; setIcon (Action.SMALL_ICON, "folder_explore_16.png"); setIcon (Action.LARGE_ICON_KEY, "folder_explore_32.png"); + + this.rootDirectory = rootDirectory; } @Override @@ -37,6 +40,7 @@ class RootDirectoryAction extends DefaultAction chooser.setFileSelectionMode (JFileChooser.DIRECTORIES_ONLY); if (rootDirectory != null) chooser.setSelectedFile (rootDirectory); + int result = chooser.showDialog (null, "Accept"); if (result == JFileChooser.APPROVE_OPTION) { @@ -46,8 +50,20 @@ class RootDirectoryAction extends DefaultAction if (file != null) { rootDirectory = file; - catalogPanel.changeRootPanel (file); + for (RootDirectoryListener listener : listeners) + listener.rootDirectoryChanged (file); } } } + + public void addListener (RootDirectoryListener listener) + { + if (!listeners.contains (listener)) + listeners.add (listener); + } + + interface RootDirectoryListener + { + public void rootDirectoryChanged (File newRootDirectory); + } } \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/gui/TreeBuilder.java b/src/com/bytezone/diskbrowser/gui/TreeBuilder.java index 5bc92d6..0d16af3 100755 --- a/src/com/bytezone/diskbrowser/gui/TreeBuilder.java +++ b/src/com/bytezone/diskbrowser/gui/TreeBuilder.java @@ -4,9 +4,8 @@ import java.awt.image.BufferedImage; import java.io.File; import java.net.URL; import java.text.SimpleDateFormat; -import java.util.*; -import java.util.zip.CRC32; -import java.util.zip.Checksum; +import java.util.Arrays; +import java.util.Date; import javax.swing.ImageIcon; import javax.swing.JComponent; @@ -15,61 +14,75 @@ import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeModel; -import com.bytezone.diskbrowser.disk.AppleDisk; -import com.bytezone.diskbrowser.disk.Disk; import com.bytezone.diskbrowser.disk.DiskFactory; import com.bytezone.diskbrowser.disk.FormattedDisk; import com.bytezone.diskbrowser.utilities.FileFormatException; +import com.bytezone.diskbrowser.utilities.Utility; public class TreeBuilder { private static SimpleDateFormat sdf = new SimpleDateFormat ("dd MMM yyyy"); - private static final boolean FULL_TREE = false; - private static final List suffixes = - Arrays.asList ("po", "dsk", "do", "hdv", "2mg", "v2d", "nib", "d13", "sdk", "gz"); + private static final int DISK_13_SIZE = 116480; + private static final int DISK_16_SIZE = 143360; + private static final int DISK_800K_SIZE = 819264; - FileComparator fc = new FileComparator (); - JTree tree; - int totalDisks; - int totalFolders; + // private static final boolean FULL_TREE_TRAVERSAL = false; - Map totalFiles = new TreeMap (); + private final FileComparator fileComparator = new FileComparator (); + private final JTree tree; - Map> duplicateDisks = - new TreeMap> (); - Map diskNames = new HashMap (); - Map> dosMap = new TreeMap> (); + // private int totalDisks; + // private int totalFolders; + + // // total files for each suffix + // private final Map typeList = new TreeMap (); + // + // // list of unique disk names -> List of File duplicates + // final Map> duplicateDisks = + // new TreeMap> (); + // + // // list of unique disk names -> File + // private final Map diskNames = new HashMap (); + // + // // list of checksum -> File + // final Map> dosMap = new TreeMap> (); public TreeBuilder (File folder) { assert (folder.exists ()); assert (folder.isDirectory ()); - FileNode fn = new FileNode (folder); - DefaultMutableTreeNode root = new DefaultMutableTreeNode (fn); - fn.setTreeNode (root); + FileNode fileNode = new FileNode (folder); + DefaultMutableTreeNode root = new DefaultMutableTreeNode (fileNode); + fileNode.setTreeNode (root); + addFiles (root, folder); DefaultTreeModel treeModel = new DefaultTreeModel (root); tree = new JTree (treeModel); treeModel.setAsksAllowsChildren (true); // allows empty nodes to appear as folders setDiskIcon ("/com/bytezone/diskbrowser/icons/disk.png"); - ((FileNode) root.getUserObject ()).disks = totalDisks; + // ((FileNode) root.getUserObject ()).disks = totalDisks; - if (FULL_TREE) - { - System.out.printf ("%nFolders ..... %,5d%n", totalFolders); - System.out.printf ("Disks ....... %,5d%n%n", totalDisks); + // if (FULL_TREE_TRAVERSAL) + // { + // System.out.printf ("%nFolders ..... %,5d%n", totalFolders); + // System.out.printf ("Disks ....... %,5d%n%n", totalDisks); + // + // int grandTotal = 0; + // for (String key : typeList.keySet ()) + // { + // int typeTotal = typeList.get (key); + // grandTotal += typeTotal; + // System.out.printf ("%13.13s %,6d%n", key + " ...........", typeTotal); + // } + // System.out.printf ("%nTotal ....... %,6d%n%n", grandTotal); + // } + } - int tf = 0; - for (String key : totalFiles.keySet ()) - { - int t = totalFiles.get (key); - tf += t; - System.out.printf ("%13.13s %,5d%n", key + " ...........", t); - } - System.out.printf ("%nTotal ...... %,6d%n%n", tf); - } + public JTree getTree () + { + return tree; } private void addFiles (DefaultMutableTreeNode node, File directory) @@ -81,124 +94,127 @@ public class TreeBuilder return; } - FileNode parentNode = (FileNode) node.getUserObject (); - Arrays.sort (files, fc); + // FileNode parentNode = (FileNode) node.getUserObject (); + Arrays.sort (files, fileComparator); + for (File file : files) { if (file.isDirectory ()) { - FileNode fn = new FileNode (file); - DefaultMutableTreeNode newNode = new DefaultMutableTreeNode (fn); - fn.setTreeNode (newNode); + FileNode fileNode = new FileNode (file); + DefaultMutableTreeNode newNode = new DefaultMutableTreeNode (fileNode); + fileNode.setTreeNode (newNode); newNode.setAllowsChildren (true); node.add (newNode); - totalFolders++; - if (FULL_TREE) - addFiles (newNode, file); // recursion! + // totalFolders++; + + // if (FULL_TREE_TRAVERSAL) + // addFiles (newNode, file); // recursion! + continue; } - if (FULL_TREE) - { - int pos = file.getName ().lastIndexOf ('.'); - if (pos > 0) - { - String type = file.getName ().substring (pos + 1).toLowerCase (); - if (totalFiles.containsKey (type)) - { - int t = totalFiles.get (type); - totalFiles.put (type, ++t); - } - else - totalFiles.put (type, 1); - } - } + // if (FULL_TREE_TRAVERSAL) + // { + // int pos = file.getName ().lastIndexOf ('.'); + // if (pos > 0) + // { + // String type = file.getName ().substring (pos + 1).toLowerCase (); + // if (typeList.containsKey (type)) + // { + // int t = typeList.get (type); + // typeList.put (type, ++t); + // } + // else + // typeList.put (type, 1); + // } + // } - if (file.length () != 143360 && file.length () != 116480 && file.length () != 819264 - && file.length () < 200000) + if (file.length () != DISK_16_SIZE && file.length () != DISK_13_SIZE + && file.length () != DISK_800K_SIZE && file.length () < 200000) { String name = file.getName ().toLowerCase (); if (!name.endsWith (".sdk") && !name.endsWith (".dsk.gz")) continue; } - parentNode.disks++; - String filename = file.getAbsolutePath (); - if (validFileType (filename)) + // parentNode.disks++; + + if (Utility.validFileType (file.getAbsolutePath ())) { - FileNode fn = new FileNode (file); - DefaultMutableTreeNode newNode = new DefaultMutableTreeNode (fn); - fn.setTreeNode (newNode); + FileNode fileNode = new FileNode (file); + DefaultMutableTreeNode newNode = new DefaultMutableTreeNode (fileNode); + fileNode.setTreeNode (newNode); newNode.setAllowsChildren (false); node.add (newNode); - if (false) - checkDuplicates (file); + // if (false) + // checkDuplicates (file); - totalDisks++; + // totalDisks++; - if (false) - checksumDos (file); + // if (false) + // checksumDos (file); } } } - private void checksumDos (File file) - { - if (file.length () != 143360 || file.getAbsolutePath ().contains ("/ZDisks/")) - return; + // private void checksumDos (File file) + // { + // if (file.length () != 143360 || file.getAbsolutePath ().contains ("/ZDisks/")) + // return; + // + // Disk disk = new AppleDisk (file, 35, 16); + // byte[] buffer = disk.readSector (0, 0); + // + // Checksum checksum = new CRC32 (); + // checksum.update (buffer, 0, buffer.length); + // long cs = checksum.getValue (); + // List files = dosMap.get (cs); + // if (files == null) + // { + // files = new ArrayList (); + // dosMap.put (cs, files); + // } + // files.add (file); + // } - Disk disk = new AppleDisk (file, 35, 16); - byte[] buffer = disk.readSector (0, 0); + // private void checkDuplicates (File file) + // { + // if (diskNames.containsKey (file.getName ())) + // { + // List diskList = duplicateDisks.get (file.getName ()); + // if (diskList == null) + // { + // diskList = new ArrayList (); + // duplicateDisks.put (file.getName (), diskList); + // diskList.add (new DiskDetails (diskNames.get (file.getName ())));// add original + // } + // diskList.add (new DiskDetails (file)); // add the duplicate + // } + // else + // diskNames.put (file.getName (), file); + // } - Checksum checksum = new CRC32 (); - checksum.update (buffer, 0, buffer.length); - long cs = checksum.getValue (); - List files = dosMap.get (cs); - if (files == null) - { - files = new ArrayList (); - dosMap.put (cs, files); - } - files.add (file); - } - - private void checkDuplicates (File file) - { - if (diskNames.containsKey (file.getName ())) - { - List diskList = duplicateDisks.get (file.getName ()); - if (diskList == null) - { - diskList = new ArrayList (); - duplicateDisks.put (file.getName (), diskList); - diskList.add (new DiskDetails (diskNames.get (file.getName ())));// add the original - } - diskList.add (new DiskDetails (file));// add the duplicate - } - else - diskNames.put (file.getName (), file); - } - - private boolean validFileType (String filename) - { - int dotPos = filename.lastIndexOf ('.'); - if (dotPos < 0) - return false; - - String suffix = filename.substring (dotPos + 1).toLowerCase (); - - int dotPos2 = filename.lastIndexOf ('.', dotPos - 1); - if (dotPos2 > 0) - { - String suffix2 = filename.substring (dotPos2 + 1, dotPos).toLowerCase (); - if (suffix.equals ("gz") && (suffix2.equals ("bxy") || suffix2.equals ("bny"))) - return false; - } - - return suffixes.contains (suffix); - } + // private boolean validFileType (String filename) + // { + // int dotPos = filename.lastIndexOf ('.'); + // if (dotPos < 0) + // return false; + // + // String suffix = filename.substring (dotPos + 1).toLowerCase (); + // + // int dotPos2 = filename.lastIndexOf ('.', dotPos - 1); + // if (dotPos2 > 0) + // { + // String suffix2 = filename.substring (dotPos2 + 1, dotPos).toLowerCase (); + // if (suffix.equals ("gz") && (suffix2.equals ("bxy") || suffix2.equals ("bny"))) + // return false; + // } + // + // return suffixes.contains (suffix); + // } private void setDiskIcon (String iconName) { @@ -341,19 +357,20 @@ public class TreeBuilder } } - private class FileComparator implements Comparator - { - @Override - public int compare (File filea, File fileb) - { - boolean fileaIsDirectory = filea.isDirectory (); - boolean filebIsDirectory = fileb.isDirectory (); - - if (fileaIsDirectory && !filebIsDirectory) - return -1; - if (!fileaIsDirectory && filebIsDirectory) - return 1; - return filea.getName ().compareToIgnoreCase (fileb.getName ()); - } - } + // private class FileComparator implements Comparator + // { + // @Override + // public int compare (File thisFile, File thatFile) + // { + // boolean thisFileIsDirectory = thisFile.isDirectory (); + // boolean thatFileIsDirectory = thatFile.isDirectory (); + // + // if (thisFileIsDirectory && !thatFileIsDirectory) + // return -1; + // if (!thisFileIsDirectory && thatFileIsDirectory) + // return 1; + // + // return thisFile.getName ().compareToIgnoreCase (thatFile.getName ()); + // } + // } } \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/utilities/Utility.java b/src/com/bytezone/diskbrowser/utilities/Utility.java index 753db8a..07556f1 100644 --- a/src/com/bytezone/diskbrowser/utilities/Utility.java +++ b/src/com/bytezone/diskbrowser/utilities/Utility.java @@ -3,9 +3,14 @@ package com.bytezone.diskbrowser.utilities; import java.awt.Graphics2D; import java.awt.Toolkit; import java.awt.geom.AffineTransform; +import java.util.Arrays; +import java.util.List; public class Utility { + public static final List suffixes = + Arrays.asList ("po", "dsk", "do", "hdv", "2mg", "v2d", "nib", "d13", "sdk", "gz"); + // not used - it doesn't work with Oracle's JDK public static boolean hasRetinaDisplay () { @@ -51,4 +56,23 @@ public class Utility return true; } + + public static boolean validFileType (String filename) + { + int dotPos = filename.lastIndexOf ('.'); + if (dotPos < 0) + return false; + + String suffix = filename.substring (dotPos + 1).toLowerCase (); + + int dotPos2 = filename.lastIndexOf ('.', dotPos - 1); + if (dotPos2 > 0) + { + String suffix2 = filename.substring (dotPos2 + 1, dotPos).toLowerCase (); + if (suffix.equals ("gz") && (suffix2.equals ("bxy") || suffix2.equals ("bny"))) + return false; + } + + return suffixes.contains (suffix); + } } \ No newline at end of file