001: package snow.files;
002:
003: import snow.utils.gui.*;
004: import java.awt.event.*;
005: import java.awt.event.MouseAdapter;
006: import java.awt.BorderLayout;
007: import snow.utils.DateUtils;
008: import snow.utils.storage.*;
009: import java.awt.Color;
010: import java.awt.Component;
011: import java.awt.Graphics;
012: import javax.swing.*;
013: import javax.swing.table.*;
014: import snow.sortabletable.*;
015: import java.util.*;
016: import java.io.*;
017:
018: /** With content last mod date statistics (min, max, median)
019: */
020: public final class DirectoryStatExplorer {
021: final File baseFolder;
022: final JFileChooser chooser;
023:
024: final int baseLength;
025: final List<Folder> folders = new ArrayList<Folder>();
026: long dateOverallMin = Long.MAX_VALUE, dateOverallMax = -1;
027: long totFileCount = 0;
028: long totSizeCount = 0;
029: final String[] columns = new String[] { "package", "files", "size",
030: "median date", "last modified dates [min, median, max]" };
031:
032: public DirectoryStatExplorer(final File baseFolder,
033: final JFileChooser chooser) {
034: this .baseFolder = baseFolder;
035: this .chooser = chooser;
036: baseLength = baseFolder.getAbsolutePath().length();
037:
038: if (baseFolder == null)
039: return;
040: if (!baseFolder.isDirectory())
041: return;
042:
043: ProgressModalDialog pmd = new ProgressModalDialog(new JFrame(),
044: "Scanning " + baseFolder.getAbsolutePath(), true);
045: pmd.start();
046:
047: List<File> allFolders = new ArrayList<File>();
048: FileUtils.getFoldersRecurse(baseFolder, allFolders, false);
049:
050: pmd.setProgressBounds(allFolders.size());
051:
052: System.out.println("" + allFolders.size()
053: + " folders found in " + baseFolder);
054:
055: for (File fi : allFolders) {
056: if (pmd.getWasCancelled()) {
057: pmd.closeDialog();
058: return;
059: }
060:
061: pmd.incrementProgress(1);
062: Folder ffi = new Folder(fi);
063: totFileCount += ffi.count;
064: totSizeCount += ffi.size;
065: folders.add(ffi);
066:
067: pmd.setProgressComment("" + folders.size() + " folders, "
068: + totFileCount + " files.");
069: }
070: pmd.closeDialog();
071:
072: view();
073:
074: }
075:
076: void view() {
077: String tit = "Folders explorer for " + totFileCount
078: + " files and " + folders.size() + " folders, "
079: + FileUtils.formatSize(totSizeCount)
080: + " [dates range: "
081: + DateUtils.dateFormatMDY.format(dateOverallMin)
082: + " - "
083: + DateUtils.dateFormatMDY.format(dateOverallMax) + "]";
084:
085: JDialog d = new JDialog(new JFrame(), tit, true); // if false, remains behind the chooser !
086: CloseControlPanel ccp = new CloseControlPanel(d, false, true,
087: "Close");
088: d.add(ccp, BorderLayout.SOUTH);
089:
090: final FoldersTableModel ftm = new FoldersTableModel();
091: final SortableTableModel stm = new SortableTableModel(ftm, 7,
092: false); // so we see first the last modified packs
093: final JTable table = new JTable(stm);
094: Renderer renderer = new Renderer();
095: stm.installGUI(table);
096: table.setDefaultRenderer(Folder.class, renderer);
097:
098: d.add(new JScrollPane(table), BorderLayout.CENTER);
099:
100: MultiSearchPanel msp = new MultiSearchPanel("Filter: ", null,
101: stm);
102: d.add(msp, BorderLayout.NORTH);
103:
104: table.addMouseListener(new MouseAdapter() {
105: @Override
106: public void mousePressed(MouseEvent me) {
107: if (me.getClickCount() == 2) {
108: int pos = stm.getIndexInUnsortedFromTablePos(table
109: .getSelectedRow());
110: Folder fi = folders.get(pos);
111: if (chooser != null) {
112: chooser.setSelectedFile(fi.folder);
113: }
114: }
115: }
116: });
117:
118: d.setSize(850, 700);
119: d.setLocation(150, 50);
120: d.setVisible(true);
121:
122: }
123:
124: /** Creates stats of the folder's content
125: */
126: class Folder {
127: final File folder;
128: final String name;
129:
130: int count = 0;
131: long size = 0;
132: long dateMin = Long.MAX_VALUE;
133: long dateMax = -1;
134: long dateMedian;
135: List<Long> dates = new ArrayList<Long>(); // used for median
136:
137: public Folder(File folder) {
138: this .folder = folder;
139: this .name = folder.getAbsolutePath().substring(baseLength);
140:
141: File[] fis = folder.listFiles();
142: if (fis != null) {
143: for (File fi : fis) {
144: if (fi.isFile()) {
145: count++;
146: size += fi.length();
147: long lm = fi.lastModified();
148:
149: if (lm > 0) {
150: dates.add(lm);
151:
152: if (lm < dateMin)
153: dateMin = lm;
154: if (lm > dateMax)
155: dateMax = lm;
156:
157: if (lm < dateOverallMin)
158: dateOverallMin = lm;
159: if (lm > dateOverallMax)
160: dateOverallMax = lm;
161: }
162:
163: }
164: }
165: }
166:
167: endStat();
168: }
169:
170: /** Must be called at the end, after all sources have been added */
171: public void endStat() {
172: if (!dates.isEmpty()) {
173: dateMedian = dates.get(dates.size() / 2);
174: }
175: dates.clear(); // no more used.
176: }
177:
178: }
179:
180: class FoldersTableModel extends FineGrainTableModel {
181: public Object getValueAt(int row, int col) {
182: Folder it = folders.get(row);
183: if (col == 0) {
184: if (it.name.length() == 0)
185: return "<unnamed scope>";
186: return it.name;
187: }
188: if (col == 1) {
189: return it.count;
190: }
191: if (col == 2) {
192: if (it.size <= 0)
193: return "";
194: return FileUtils.formatSize(it.size);
195: }
196: if (col == 3) {
197: if (it.dateMedian <= 0)
198: return "";
199: return DateUtils.dateFormatMDY.format(it.dateMedian);
200: }
201: if (col == 4) {
202: return it;
203: /*DateUtils.dateFormatMDY.format( it.dateMin ) + " - "+ DateUtils.dateFormatMDY.format( it.dateMedian )
204: +" - "+DateUtils.dateFormatMDY.format( it.dateMax );*/
205: }
206:
207: return "?";
208: }
209:
210: public int getColumnAlignment(int column) {
211: if (column == 0)
212: return JLabel.LEFT;
213: return JLabel.RIGHT;
214: }
215:
216: int[] COLUMN_PREFERED_SIZES = new int[] { 26, 4, 4, 8, 20 };
217:
218: @Override
219: public int getPreferredColumnWidth(int column) {
220: if (column >= 0 && column < COLUMN_PREFERED_SIZES.length)
221: return COLUMN_PREFERED_SIZES[column];
222: return -1;
223: }
224:
225: @Override
226: public int compareForColumnSort(int row1, int row2, int col) {
227: if (col == 2) {
228: return Long.valueOf(folders.get(row1).size).compareTo(
229: folders.get(row2).size);
230: }
231:
232: if (col == 3) {
233: return Long.valueOf(folders.get(row1).dateMedian)
234: .compareTo(folders.get(row2).dateMedian);
235: }
236: if (col == 4) {
237: // of interrest: look at last mod ! first not very useful
238: return Long.valueOf(folders.get(row1).dateMax)
239: .compareTo(folders.get(row2).dateMax);
240: }
241:
242: // use the getValueAt
243: return super .compareForColumnSort(row1, row2, col);
244: }
245:
246: @Override
247: public String getColumnName(int col) {
248: return columns[col];
249: }
250:
251: public int getRowCount() {
252: return folders.size();
253: }
254:
255: public int getColumnCount() {
256: return columns.length;
257: }
258:
259: @Override
260: public boolean isCellEditable(int r, int c) {
261: return false;
262: }
263:
264: }
265:
266: class Renderer extends DefaultTableCellRenderer {
267: RendererIm rim = new RendererIm();
268:
269: public Component getTableCellRendererComponent(JTable table,
270: Object value, boolean isSelected, boolean hasFocus,
271: int row, int column) {
272: if (column == 4) {
273: //rim.setPreferredSize( getPreferredSize() );
274: if (isSelected) {
275: rim.setBackground(UIManager
276: .getColor("Table.selectionBackground"));
277: } else {
278: rim.setBackground(UIManager
279: .getColor("Table.background"));
280: }
281: rim.set((Folder) value);
282: return rim;
283: }
284: return super .getTableCellRendererComponent(table, value,
285: isSelected, hasFocus, row, column);
286: }
287: }
288:
289: class RendererIm extends JPanel {
290: Folder pi;
291:
292: public RendererIm() {
293: super ();
294: //setBackground(table.getBackground()); //Color.white);
295: //setSize(200,20);
296: }
297:
298: public void set(Folder pi) {
299: this .pi = pi;
300: }
301:
302: @Override
303: public void paintComponent(Graphics gr) {
304: super .paintComponent(gr); // border, background, ...
305: if (pi == null)
306: return;
307: if (dateOverallMax < 0)
308: return;
309:
310: // gray bloc from min to max
311: gr.setColor(Color.lightGray);
312: int min = (int) (relPosDate(pi.dateMin) * getWidth());
313: int max = (int) (relPosDate(pi.dateMax) * getWidth());
314: gr.fillRect(min, 2, max - min, getHeight() - 4);
315: int med = (int) (relPosDate(pi.dateMedian) * getWidth());
316: gr.setColor(Color.darkGray);
317: gr.fillRect(med, 0, 1, getHeight());
318: }
319: }
320:
321: // in [0,1]
322: private double relPosDate(final long d) {
323: return (1.0 * (d - dateOverallMin))
324: / (dateOverallMax - dateOverallMin);
325: }
326:
327: public static void main(String[] args) {
328: FileChooserFilter.main(args);
329: }
330:
331: }
|