Moving duplicate handler

This commit is contained in:
Denis Molony 2016-12-07 21:42:01 +11:00
parent bce29f8714
commit bd1cea9ab2
12 changed files with 498 additions and 304 deletions

View File

@ -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 ();
}

View File

@ -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;
}
}

View File

@ -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");
}
}

View File

@ -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<String, Integer> typeList = new TreeMap<String, Integer> ();
// list of unique disk names -> List of File duplicates
final Map<String, List<DiskDetails>> duplicateDisks =
new TreeMap<String, List<DiskDetails>> ();
// list of unique disk names -> File
private final Map<String, File> diskNames = new HashMap<String, File> ();
// list of checksum -> File
final Map<Long, List<File>> dosMap = new TreeMap<Long, List<File>> ();
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<File> files = dosMap.get (cs);
if (files == null)
{
files = new ArrayList<File> ();
dosMap.put (cs, files);
}
files.add (file);
}
private void checkDuplicates (File file)
{
if (diskNames.containsKey (file.getName ()))
{
List<DiskDetails> diskList = duplicateDisks.get (file.getName ());
if (diskList == null)
{
diskList = new ArrayList<DiskDetails> ();
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"));
}
}

View File

@ -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)
{

View File

@ -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 ();

View File

@ -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<String, List<DiskDetails>> 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<String, List<DiskDetails>> duplicateDisks)
// public void setDuplicates (File rootFolder,
// Map<String, List<DiskDetails>> 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<DiskDetails> disksSelected = new ArrayList<DiskDetails> ();
List<DuplicatePanel> duplicatePanels = new ArrayList<DuplicateAction.DuplicatePanel> ();
List<DuplicatePanel> duplicatePanels =
new ArrayList<DuplicateAction.DuplicatePanel> ();
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<DiskDetails> 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<DiskDetails> duplicateDisks;
public DuplicatePanel (List<DiskDetails> duplicateDisks, int folderNameLength,
List<DiskDetails> disksSelected, JButton deleteButton, JButton clearButton)
List<DiskDetails> 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<DiskDetails> disksSelected,
JButton deleteButton, JButton clearButton)
public CheckBoxActionListener (DiskDetails diskDetails,
List<DiskDetails> 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;
}

View File

@ -0,0 +1,22 @@
package com.bytezone.diskbrowser.gui;
import java.io.File;
import java.util.Comparator;
public class FileComparator implements Comparator<File>
{
@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 ());
}
}

View File

@ -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<String, List<DiskDetails>> duplicateDisks;
// Map<String, List<DiskDetails>> 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);

View File

@ -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<RootDirectoryListener> listeners =
new ArrayList<RootDirectoryAction.RootDirectoryListener> ();
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);
}
}

View File

@ -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<String> 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<String, Integer> totalFiles = new TreeMap<String, Integer> ();
private final FileComparator fileComparator = new FileComparator ();
private final JTree tree;
Map<String, List<DiskDetails>> duplicateDisks =
new TreeMap<String, List<DiskDetails>> ();
Map<String, File> diskNames = new HashMap<String, File> ();
Map<Long, List<File>> dosMap = new TreeMap<Long, List<File>> ();
// private int totalDisks;
// private int totalFolders;
// // total files for each suffix
// private final Map<String, Integer> typeList = new TreeMap<String, Integer> ();
//
// // list of unique disk names -> List of File duplicates
// final Map<String, List<DiskDetails>> duplicateDisks =
// new TreeMap<String, List<DiskDetails>> ();
//
// // list of unique disk names -> File
// private final Map<String, File> diskNames = new HashMap<String, File> ();
//
// // list of checksum -> File
// final Map<Long, List<File>> dosMap = new TreeMap<Long, List<File>> ();
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<File> files = dosMap.get (cs);
// if (files == null)
// {
// files = new ArrayList<File> ();
// 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<DiskDetails> diskList = duplicateDisks.get (file.getName ());
// if (diskList == null)
// {
// diskList = new ArrayList<DiskDetails> ();
// 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<File> files = dosMap.get (cs);
if (files == null)
{
files = new ArrayList<File> ();
dosMap.put (cs, files);
}
files.add (file);
}
private void checkDuplicates (File file)
{
if (diskNames.containsKey (file.getName ()))
{
List<DiskDetails> diskList = duplicateDisks.get (file.getName ());
if (diskList == null)
{
diskList = new ArrayList<DiskDetails> ();
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<File>
{
@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<File>
// {
// @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 ());
// }
// }
}

View File

@ -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<String> 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);
}
}