Save This Page
Home » openjdk-7 » net.sourceforge » neonzip » [javadoc | source]
    1   /*
    2    *  NeonZip - archive tool
    3    *  Copyright (C) 2001 Peter Ivanov
    4    *
    5    *  This program is free software; you can redistribute it and/or
    6    *  modify it under the terms of the GNU General Public License
    7    *  as published by the Free Software Foundation; either version 2
    8    *  of the License, or (at your option) any later version.
    9    *
   10    *  This program is distributed in the hope that it will be useful,
   11    *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   12    *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13    *  GNU General Public License for more details.
   14    *
   15    *  You should have received a copy of the GNU General Public License
   16    *  along with this program; if not, write to the Free Software
   17    *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   18    *
   19    *
   20    *	@author    Peter Ivanov
   21    * 	           <a href=mailto:peterivanov@europe.com>peterivanov@europe.com</a>,
   22    * 	           <br>Copyright (c) 2001 Peter K. Ivanov.
   23    *
   24    * 	@version   (December 30 2001)
   25    *
   26    */
   27   
   28   package net.sourceforge.neonzip;
   29   
   30   import javax.swing;
   31   import javax.swing.event;
   32   import javax.swing.table;
   33   import javax.swing.border;
   34   import java.awt;
   35   import java.awt.event;
   36   import java.awt.dnd;
   37   import java.awt.datatransfer;
   38   import java.util;
   39   import java.io;
   40   import java.text;
   41   import java.net.URL;
   42   
   43   import gnu.regexp;
   44   import org.apache.log4j;
   45   
   46   public final class Main extends JFrame {
   47   	
   48   	Thread currentOperation;
   49   	
   50   	Category log = Category.getInstance("neonzip.Main");
   51   	
   52   	public final static String TITLE = "NeonZip";
   53   	public final static int WIDTH = 610;
   54   	public final static int HEIGHT = 450;
   55   	
   56   	/* File Menu History */
   57   	private JMenu fMenuFile;
   58   	private JMenu fMenuRecent;
   59   	private FileHistoryManager fFileHistory;
   60   	
   61   	/* List with last extraction paths */
   62   	private Vector fPathList;
   63   	private final static int fMaxExtractHistory = 6;
   64   	
   65   	/* Properties manager */
   66   	private Utils.PropertiesManager fPropManager;
   67   	
   68   	/* Properties */
   69   	private File fExtractDir;
   70   	
   71   	/* Internationalization resources */
   72   	public static ResourceBundle fResources;
   73   	
   74   	/* Actions */
   75   	private ExitAction exitAction;
   76   	private SortingAction sortingAction;
   77   	private OpenArchiveAction openArchiveAction;
   78   	private NewArchiveAction newArchiveAction;
   79   	private CloseArchiveAction closeArchiveAction;
   80   	private AddAction addAction;
   81   	private DeleteAction deleteAction;
   82   	private ExtractAction extractAction;
   83   	private SelectAllAction selectAllAction;
   84   	private InvertSelectionAction invertSelectionAction;
   85   	private LastOutputAction lastOutputAction;
   86   	private LastOpenHistoryAction lastOpenHistoryAction;
   87   	private TestIntegrityAction testIntegrityAction;
   88   	
   89   	/* Main Table Component */
   90   	private ArchiveTable fTable;
   91   	
   92   	/* Table Model - customized functionality */
   93   	private ArchiveTableModel fTableModel;
   94   	//private DefaultTableModel fTableModel;
   95   	
   96   	/* Archive Supports */
   97   	private ArchiveSupport fSupport;
   98   	
   99   	/* JTable data and columns */
  100   	private Vector fColumnNames;
  101   	private Vector fTableData;
  102   	
  103   	private Vector fColumnsMaped;
  104   	
  105   	/* Point to current system locale */
  106   	private Locale fLocale;
  107   	
  108   	/* Localized data and time formatter (middle data/time format) */
  109   	public static DateFormat fDateFormat;
  110   	
  111   	/* Last log output manager */
  112   	private Utils.OutputManager fOutputManager;
  113   	
  114   	/* Status bar labels */
  115   	private JLabel fLeftStatusLabel;
  116   	private JLabel fRightStatusLabel;
  117   	
  118   	/* Some predefined string for more optimization */
  119   	private String strTotal;
  120   	private String strFiles;
  121   	private String strSelected;
  122   	private String strBytes;
  123   	
  124   	/* Progress monitor */
  125   	private NeonMonitor fMonitor;
  126   	private Thread fMonitorThread;
  127   	
  128   	/**
  129   	*	Main class constructor
  130   	*/
  131   	public Main() {
  132   		super();
  133   		
  134   		log.info("NeonZip starting...");
  135   		
  136   		/* Determinate current locale */
  137   		fLocale = Locale.getDefault();
  138   		
  139   		/* Internationalization bundles */
  140   		defineInternationalizationBundles();
  141   		
  142   		/* Some predefined string for more optimization */
  143   		strTotal = fResources.getString("key.label.total") + " ";
  144   		strFiles = fResources.getString("key.label.files") + ", ";
  145   		strSelected = fResources.getString("key.label.selected") + " ";
  146   		strBytes = " " + fResources.getString("key.label.bytes");
  147   		
  148   		/* Recent files history manager */
  149   		fFileHistory = new FileHistoryManager();
  150   		
  151   		/* Components initialization */
  152   		initComponents();
  153   		
  154   		/* Properties manager */
  155   		fPropManager = new Utils.PropertiesManager();
  156   		fPropManager.setAutoStore(false);
  157   		loadProperties();
  158   		
  159   		/* Medium data/time format for table */
  160   		defineDataTimeFormat();
  161   		
  162   		/* Crate some directories if is needed */
  163   		handleAppDirs();
  164   		
  165   		/* Last log output manager */
  166   		fOutputManager = new Utils.OutputManager();
  167   		
  168   		/* Monitor for operations progress */
  169   		fMonitor = new NeonMonitor(this);
  170   
  171   		// force zip support only for development needs
  172   		fSupport = new ZipSupport(this, fOutputManager, fTable, fTableData);
  173   		
  174   		setGlassPane(new GlassComponent());
  175   	}
  176   	
  177   	
  178   	
  179   	/**
  180   	*	This method can be invoked inside archive supports.
  181   	*	And is very similar to Open archive operation for current support.
  182   	*/
  183   	public void refreshTable(File aCurrentArchive) {
  184   		// clear old table content
  185   		fTableData.clear();
  186   		
  187   		Vector zipData = null;
  188   		
  189   		// invoke archive support interface
  190   		try {
  191   			zipData = fSupport.open(aCurrentArchive);
  192   		} catch (Exception e) {
  193   			log.error("Error open file", e);
  194   		}
  195   		if (zipData == null) return;
  196   		//log.debug("Data in zip VECTOR: " + zipData.size());
  197   		
  198   		fTableData.addAll(zipData);
  199   		fTable.updateUI();
  200   		setTitle(TITLE + " - " + Utils.removePath(aCurrentArchive.toString()));
  201   		
  202   		// clear previous selection
  203   		ListSelectionModel tableSelection = fTable.getSelectionModel();
  204   		//tableSelection.setLeadSelectionIndex(0);
  205   		tableSelection.clearSelection();
  206   		
  207   		this.setDefaultRightStatusMessage();
  208   	}
  209   	
  210   	
  211   	/**
  212   	*	Components initialization.
  213   	*/
  214   	private void initComponents() {
  215   		setTitle(TITLE);
  216   		setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
  217   		addWindowListener(new WindowAdapter() {
  218   			public void windowClosing(WindowEvent e) {
  219   				appClosing(e);
  220   			}
  221   		});
  222   		
  223   		JPanel root = new JPanel(new BorderLayout());
  224   		JToolBar toolbar = new JToolBar();
  225   		JPanel content = new JPanel(new BorderLayout());
  226   		JPanel statusbar = new JPanel(new GridLayout(1, 2));
  227   		
  228   		/* Status bar */
  229   		statusbar.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
  230   		fLeftStatusLabel = new JLabel(" ");
  231   		fRightStatusLabel = new JLabel(" ");
  232   		statusbar.add(fLeftStatusLabel);
  233   		statusbar.add(fRightStatusLabel);
  234   		
  235   		root.add(toolbar, "North");
  236   		root.add(content, "Center");
  237   		content.add(statusbar, "South");
  238   		
  239   		getContentPane().add(root);
  240   		
  241   		/* Table initialization */
  242   		fColumnNames = initColumnNames();
  243   		fTableData = new Vector();
  244   		
  245   		fTable = new ArchiveTable(fTableData, fColumnNames);
  246   		fTableModel = new ArchiveTableModel();
  247   		fTable.setModel(fTableModel);
  248   		fTable.setShowGrid(false);
  249   		fTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
  250   		fTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
  251   		fTable.setBackground(Color.white);
  252   		//fTable.setPreferredScrollableViewportSize(new Dimension(WIDTH, HEIGHT));
  253   		JScrollPane tablePane = new JScrollPane(fTable, 
  254   							ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
  255   							ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
  256   		JViewport viewport = tablePane.getViewport();
  257   		viewport.setBackground(Color.white);
  258   		viewport.setDropTarget(new DropTarget(viewport, new ViewportDropTargetListener()));
  259   		ListSelectionModel selectModel = fTable.getSelectionModel();
  260   		selectModel.addListSelectionListener(new ListSelectionListener() {
  261   			public void valueChanged(ListSelectionEvent e) {
  262   				selectionListenerValueChanged(e);
  263   			}
  264   		});
  265   		// prepare table header to handle sorting
  266   		JTableHeader header = fTable.getTableHeader();
  267   		header.setUpdateTableInRealTime(true);
  268   		header.addMouseListener(fTableModel.new ColumnListener());
  269   		header.setReorderingAllowed(true);
  270   		this.initTableCellRenderer();
  271   		this.initColumnIdentifiers();
  272   		/* End table */
  273   
  274   		content.add(tablePane, "Center");
  275   		
  276   		/* Actions */
  277   		exitAction = new ExitAction();
  278   		sortingAction = new SortingAction();
  279   		openArchiveAction = new OpenArchiveAction();
  280   		newArchiveAction = new NewArchiveAction();
  281   		closeArchiveAction = new CloseArchiveAction();
  282   		addAction = new AddAction();
  283   		deleteAction = new DeleteAction();
  284   		extractAction = new ExtractAction();
  285   		selectAllAction = new SelectAllAction();
  286   		invertSelectionAction = new InvertSelectionAction();
  287   		lastOutputAction = new LastOutputAction();
  288   		lastOpenHistoryAction = new LastOpenHistoryAction();
  289   		testIntegrityAction = new TestIntegrityAction();
  290   		/* End actions */
  291   		
  292   		/* Toolbar */
  293   		JButton btnNewArchive = toolbar.add(newArchiveAction);
  294   		btnNewArchive.setIcon(loadImage("images/new_archive.png"));
  295   		btnNewArchive.setText("");
  296   		btnNewArchive.setToolTipText(fResources.getString("key.menu.new_archive"));
  297   		
  298   		JButton btnOpenArchive = toolbar.add(openArchiveAction);
  299   		btnOpenArchive.setIcon(loadImage("images/open_archive.png"));
  300   		btnOpenArchive.setText("");
  301   		btnOpenArchive.setToolTipText(fResources.getString("key.menu.open_archive"));
  302   		
  303   		JButton btnCloseArchive = toolbar.add(closeArchiveAction);
  304   		btnCloseArchive.setIcon(loadImage("images/close_archive.png"));
  305   		btnCloseArchive.setText("");
  306   		btnCloseArchive.setToolTipText(fResources.getString("key.menu.close_archive"));
  307   		
  308   		toolbar.addSeparator();
  309   		
  310   		JButton btnAdd = toolbar.add(addAction);
  311   		btnAdd.setIcon(loadImage("images/add.png"));
  312   		btnAdd.setText("");
  313   		btnAdd.setToolTipText(fResources.getString("key.menu.add"));
  314   		
  315   		JButton btnDelete = toolbar.add(deleteAction);
  316   		btnDelete.setIcon(loadImage("images/delete.png"));
  317   		btnDelete.setText("");
  318   		btnDelete.setToolTipText(fResources.getString("key.menu.delete"));
  319   		
  320   		JButton btnExtract = toolbar.add(extractAction);
  321   		btnExtract.setIcon(loadImage("images/extract.png"));
  322   		btnExtract.setText("");
  323   		btnExtract.setToolTipText(fResources.getString("key.menu.extract"));
  324   		
  325   		/* Menus */
  326   		JMenuBar mainMenu = new JMenuBar();
  327   		setJMenuBar(mainMenu);
  328   		
  329   		// File menu
  330   		fMenuFile = new JMenu(fResources.getString("key.menu.file"));
  331   		fMenuFile.setMnemonic(KeyEvent.VK_F);
  332   		mainMenu.add(fMenuFile);
  333   		
  334   		// New Archive
  335   		JMenuItem menuNewArchive = new JMenuItem(newArchiveAction);
  336   		menuNewArchive.setMnemonic(KeyEvent.VK_N);
  337   		menuNewArchive.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, 
  338   			ActionEvent.CTRL_MASK));
  339   		fMenuFile.add(menuNewArchive);
  340   		
  341   		// Open Archive
  342   		JMenuItem menuOpenArchive = new JMenuItem(openArchiveAction);
  343   		menuOpenArchive.setMnemonic(KeyEvent.VK_O);
  344   		menuOpenArchive.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, 
  345   			ActionEvent.CTRL_MASK));
  346   		fMenuFile.add(menuOpenArchive);
  347   		
  348   		// Close Archive
  349   		JMenuItem menuCloseArchive = new JMenuItem(closeArchiveAction);
  350   		menuCloseArchive.setMnemonic(KeyEvent.VK_C);
  351   		menuCloseArchive.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, 
  352   			ActionEvent.SHIFT_MASK));
  353   		fMenuFile.add(menuCloseArchive);
  354   		fMenuFile.addSeparator();
  355   		
  356   		// Recent Files
  357   		fMenuRecent = new JMenu();
  358   		fMenuRecent.setText(Main.fResources.getString("key.menu.recent_files"));
  359   		fMenuRecent.addMenuListener(new RecentFilesMenuListener());
  360   		fMenuFile.add(fMenuRecent);
  361   		
  362   		// Exit
  363   		fMenuFile.addSeparator();
  364   		JMenuItem menuExit = new JMenuItem(exitAction);
  365   		menuExit.setMnemonic(KeyEvent.VK_X);
  366   		menuExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, 
  367   			ActionEvent.ALT_MASK));
  368   		fMenuFile.add(menuExit);
  369   		
  370   		// Actions menu
  371   		JMenu menuActions = new JMenu(fResources.getString("key.menu.actions"));
  372   		menuActions.setMnemonic(KeyEvent.VK_A);
  373   		mainMenu.add(menuActions);
  374   		
  375   		// Add
  376   		JMenuItem menuAdd = new JMenuItem(addAction);
  377   		menuAdd.setMnemonic(KeyEvent.VK_A);
  378   		menuAdd.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, 
  379   			ActionEvent.SHIFT_MASK));
  380   		menuActions.add(menuAdd);
  381   		
  382   		// Delete
  383   		JMenuItem menuDelete = new JMenuItem(deleteAction);
  384   		menuDelete.setMnemonic(KeyEvent.VK_D);
  385   		menuDelete.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, 
  386   			ActionEvent.SHIFT_MASK));
  387   		menuActions.add(menuDelete);
  388   		
  389   		// Extract
  390   		JMenuItem menuExtract = new JMenuItem(extractAction);
  391   		menuExtract.setMnemonic(KeyEvent.VK_E);
  392   		menuExtract.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, 
  393   			ActionEvent.SHIFT_MASK));
  394   		menuActions.add(menuExtract);
  395   		
  396   		// Separator
  397   		menuActions.addSeparator();
  398   		
  399   		// Select All
  400   		JMenuItem menuSelectAll = new JMenuItem(selectAllAction);
  401   		menuSelectAll.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, 
  402   			ActionEvent.CTRL_MASK));
  403   		menuActions.add(menuSelectAll);
  404   		
  405   		// Invert Selection
  406   		JMenuItem menuInvertSelection = new JMenuItem(invertSelectionAction);
  407   		menuActions.add(menuInvertSelection);
  408   		
  409   		// Separator
  410   		menuActions.addSeparator();
  411   		
  412   		// Test integrity
  413   		JMenuItem menuTestIntegrity = new JMenuItem(testIntegrityAction);
  414   		menuTestIntegrity.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, 
  415   			ActionEvent.SHIFT_MASK));
  416   		menuActions.add(menuTestIntegrity);
  417   		
  418   		// Options
  419   		JMenu menuOptions = new JMenu(fResources.getString("key.menu.options"));
  420   		menuOptions.setMnemonic(KeyEvent.VK_O);
  421   		menuOptions.addMenuListener(new OptionsMenuListener());
  422   		mainMenu.add(menuOptions);
  423   		
  424   		// Sort
  425   		JMenu menuSorting = new JMenu(fResources.getString("key.menu.Sort"));
  426   		menuSorting.addMenuListener(new SortingMenuListener());
  427   		menuOptions.add(menuSorting);
  428   		
  429   		// Sort by Name
  430   		JRadioButtonMenuItem menuNameSort = 
  431   				new JRadioButtonMenuItem(sortingAction);
  432   		menuNameSort.setText(fResources.getString("key.menu.byName"));
  433   		menuNameSort.setSelected(true);
  434   		menuNameSort.setActionCommand("Name");
  435   		menuSorting.add(menuNameSort);
  436   		
  437   		// Sort by Type
  438   		JRadioButtonMenuItem menuTypeSort = 
  439   				new JRadioButtonMenuItem(sortingAction);
  440   		menuTypeSort.setText(fResources.getString("key.menu.byType"));
  441   		menuTypeSort.setActionCommand("Type");
  442   		menuSorting.add(menuTypeSort);
  443   		
  444   		// Sort by date
  445   		JRadioButtonMenuItem menuDateSort = 
  446   				new JRadioButtonMenuItem(sortingAction);
  447   		menuDateSort.setText(fResources.getString("key.menu.byDate"));
  448   		menuDateSort.setActionCommand("Modified");
  449   		menuSorting.add(menuDateSort);
  450   		
  451   		// Sort by size
  452   		JRadioButtonMenuItem menuSizeSort = 
  453   				new JRadioButtonMenuItem(sortingAction);
  454   		menuSizeSort.setText(fResources.getString("key.menu.bySize"));
  455   		menuSizeSort.setActionCommand("Size");
  456   		menuSorting.add(menuSizeSort);
  457   		
  458   		// Sort by compression ratio
  459   		JRadioButtonMenuItem menuCompressionSort = 
  460   				new JRadioButtonMenuItem(sortingAction);
  461   		menuCompressionSort.setText(fResources.getString("key.menu.byCompression_ratio"));
  462   		menuCompressionSort.setActionCommand("Ratio");
  463   		menuSorting.add(menuCompressionSort);
  464   		
  465   		// Sort by packed size
  466   		JRadioButtonMenuItem menuPackedSort = 
  467   				new JRadioButtonMenuItem(sortingAction);
  468   		menuPackedSort.setText(fResources.getString("key.menu.byPacked_size"));
  469   		menuPackedSort.setActionCommand("Packed");
  470   		menuSorting.add(menuPackedSort);
  471   		
  472   		// Sort by CRC
  473   		JRadioButtonMenuItem menuCRCSort = 
  474   				new JRadioButtonMenuItem(sortingAction);
  475   		menuCRCSort.setText(fResources.getString("key.menu.byCRC"));
  476   		menuCRCSort.setActionCommand("CRC");
  477   		menuSorting.add(menuCRCSort);
  478   		
  479   		// Sort by Path
  480   		JRadioButtonMenuItem menuPathSort = 
  481   				new JRadioButtonMenuItem(sortingAction);
  482   		menuPathSort.setText(fResources.getString("key.menu.byPath"));
  483   		menuPathSort.setActionCommand("Path");
  484   		menuSorting.add(menuPathSort);
  485   		
  486   		// Sorting button group
  487   		ButtonGroup sorting = new ButtonGroup();
  488   		sorting.add(menuNameSort);
  489   		sorting.add(menuTypeSort);
  490   		sorting.add(menuDateSort);
  491   		sorting.add(menuSizeSort);
  492   		sorting.add(menuCompressionSort);
  493   		sorting.add(menuPackedSort);
  494   		sorting.add(menuCRCSort);
  495   		sorting.add(menuPathSort);
  496   		
  497   		// Separator
  498   		menuOptions.addSeparator();
  499   		
  500   		// View Last Output
  501   		JMenuItem menuLastOutput = new JMenuItem(lastOutputAction);
  502   		menuLastOutput.setMnemonic(KeyEvent.VK_W);
  503   		menuOptions.add(menuLastOutput);
  504   		
  505   		/* End menus */
  506   	}
  507   	
  508   	
  509   	
  510   	/**
  511   	*	Define default names of table columns. We will give this data
  512   	*	to Table object.
  513   	*	@return Vector with default column names.
  514   	*/
  515   	private final Vector initColumnNames() {
  516   		Vector result = new Vector(8);
  517   		result.add(fResources.getString("key.table.name"));
  518   		result.add(fResources.getString("key.table.type"));
  519   		result.add(fResources.getString("key.table.modified"));
  520   		result.add(fResources.getString("key.table.size"));
  521   		result.add(fResources.getString("key.table.ratio"));
  522   		result.add(fResources.getString("key.table.packed"));
  523   		result.add(fResources.getString("key.table.crc"));
  524   		result.add(fResources.getString("key.table.path"));
  525   		
  526   		return result;
  527   	}
  528   	
  529   	
  530   	
  531   	/**
  532   	*	Init column identifiers. This is way to separate real column names
  533   	*	from column names visible to the users.
  534   	*/
  535   	private final void initColumnIdentifiers() {
  536   		TableColumnModel columnModel = fTable.getColumnModel();
  537   		TableColumn column0 = columnModel.getColumn(0);
  538   		TableColumn column1 = columnModel.getColumn(1);
  539   		TableColumn column2 = columnModel.getColumn(2);
  540   		TableColumn column3 = columnModel.getColumn(3);
  541   		TableColumn column4 = columnModel.getColumn(4);
  542   		TableColumn column5 = columnModel.getColumn(5);
  543   		TableColumn column6 = columnModel.getColumn(6);
  544   		TableColumn column7 = columnModel.getColumn(7);
  545   		
  546   		column0.setIdentifier("name");
  547   		column1.setIdentifier("type");
  548   		column2.setIdentifier("modified");
  549   		column3.setIdentifier("size");
  550   		column4.setIdentifier("ratio");
  551   		column5.setIdentifier("packed");
  552   		column6.setIdentifier("crc");
  553   		column7.setIdentifier("path");
  554   	}
  555   	
  556   	
  557   	
  558   	/**
  559   	*	Define local specific data and time format.
  560   	*	yyyy-m-dd hh:mm:ss
  561   	*/
  562   	private final void defineDataTimeFormat() {
  563   		fDateFormat = DateFormat.getDateTimeInstance(	DateFormat.MEDIUM,
  564   														DateFormat.MEDIUM,
  565   														fLocale);
  566   	}
  567   	
  568   	
  569   	
  570   	/**
  571   	*	Define local specific resources. Every kind of component support
  572   	*	separate bundle for internationalization strings.
  573   	*/
  574   	private final void defineInternationalizationBundles() {
  575   		try {
  576   			fResources = ResourceBundle.getBundle("net.sourceforge.neonzip.resources.ResourcesBundle", fLocale);
  577   		} catch (MissingResourceException e) {
  578   			// TO Do - add more logic here
  579   			log.error("language specific resources missing", e);
  580   			e.printStackTrace();
  581   		}
  582   	}
  583   	
  584   	
  585   	
  586   	/**
  587   	*	Close application event.
  588   	*	@param aEvent window change status event
  589   	*/
  590   	private void appClosing(WindowEvent aEvent) {
  591   		saveProperties();
  592   		System.exit(0);
  593   	}
  594   	
  595   	
  596   	
  597   	/**
  598   	*	Set specific cell renderer for columns to customize columns behaviour.
  599   	*/
  600   	private void initTableCellRenderer() {
  601   		ArchiveTableCellRenderer cellRenderer = new ArchiveTableCellRenderer();
  602   		TableColumnModel columnModel = fTable.getColumnModel();
  603   		int columnCount = columnModel.getColumnCount();
  604   		for (int i = 0; i < columnCount; i++) {
  605   			TableColumn column = columnModel.getColumn(i);
  606   			if (i > 0) {
  607   				column.setCellRenderer(cellRenderer);
  608   			}
  609   		}
  610   	}
  611   	
  612   	
  613   	
  614   	/**
  615   	*	Table row selection listener for table selection changes.
  616   	*	aEvent selection changes event
  617   	*/
  618   	private void selectionListenerValueChanged(ListSelectionEvent aEvent) {
  619   		DefaultListSelectionModel selModel = (DefaultListSelectionModel) aEvent.getSource();
  620   		if (selModel.getValueIsAdjusting()) return;
  621   		setDefaultLeftStatusMessage();
  622   	}
  623   	
  624   	
  625   	
  626   	/**
  627   	*	Handle some directories if is needed. Example: Create application
  628   	*	home directory if directory missing. For example when application 
  629   	*	runs for the first time home directory missing.
  630   	*/
  631   	private void handleAppDirs() {
  632   		// application home directory
  633   		if (!Utils.hasAppHomeDir()) {
  634   			Utils.createAppHomeDir();
  635   		}
  636   		// application temporary directory
  637   		if (!Utils.hasTempDir()) {
  638   			Utils.createTempDir();
  639   		}
  640   	}
  641   	
  642   	
  643   	
  644   	/**
  645   	*	Handle application properties saving. Set properties to properties
  646   	*	manager and after that invoke PropertiesManages.store() method 
  647   	*	and save all app properties to file.
  648   	*/
  649   	private void saveProperties() {
  650   		// Save table columns count and width and names
  651   		TableColumnModel columnModel = fTable.getColumnModel();
  652   		int columnCount = columnModel.getColumnCount();
  653   		fPropManager.setProperty("columns.count", columnCount);
  654   		for (int i = 0; i < columnCount; i++) {
  655   			TableColumn column = columnModel.getColumn(i);
  656   			int columnWidth = column.getPreferredWidth();
  657   			fPropManager.setProperty("column" + i + ".width", columnWidth);
  658   			String name = fTable.getColumnName(i);
  659   			// removing ascending mark in column name
  660   			name = name.replace('>', ' ');
  661   			name = name.replace('<', ' ');
  662   			name = name.trim();
  663   			//// end removing
  664   			fPropManager.setProperty("column" + i + ".name", name);
  665   		}
  666   		
  667   		// Save Main Window bounds (size and position)
  668   		Rectangle bounds = this.getBounds();
  669   		fPropManager.setProperty("frame.x", bounds.x);
  670   		fPropManager.setProperty("frame.y", bounds.y);
  671   		fPropManager.setProperty("frame.width", bounds.width);
  672   		fPropManager.setProperty("frame.height", bounds.height);
  673   		
  674   		// Save last extraction directory
  675   		fPropManager.setProperty("extract.lastFolder", fExtractDir.toString());
  676   		
  677   		// Sorted column
  678   		String sortColumn = (String) fColumnNames.get(fTableModel.getSortingColumn());
  679   		fPropManager.setProperty("sorting.column", sortColumn);
  680   		
  681   		// Extraction path history
  682   		for (int i = 0; i < fPathList.size(); i++) {
  683   			if (i > fMaxExtractHistory) break;
  684   			String path = (String) fPathList.get(i);
  685   			fPropManager.setProperty("extract.path" + i, path);
  686   		}
  687   		
  688   		// save last open archives history
  689   		int size = fFileHistory.size();
  690   		for (int i = 0; i < size; i++) {
  691   			String path = null;
  692   			try {
  693   				path = fFileHistory.get(i);
  694   			} catch (ArrayIndexOutOfBoundsException e) {
  695   				break;
  696   			}
  697   			fPropManager.setProperty("file.path" + i, path);
  698   		}
  699   		
  700   		fPropManager.store();
  701   	}
  702   	
  703   	
  704   	
  705   	/**
  706   	*	Load properties from file thru PropertiesManager and apply to 
  707   	*	the objects.
  708   	*/
  709   	private void loadProperties() {
  710   		// Read and set table columns width and names
  711   		Vector names = new Vector(initColumnNames());
  712   		fColumnsMaped = names;
  713   		TableColumnModel columnModel = fTable.getColumnModel();
  714   		int columnCount = fPropManager.getIntProperty("columns.count", 8);
  715   		
  716   		for (int i = 0; i < columnCount; i++) {
  717   			String name = null;
  718   			try {
  719   				name = fPropManager.getProperty("column" + i + ".name", 
  720   												(String) fColumnNames.get(i));
  721   			} catch(ArrayIndexOutOfBoundsException e) {
  722   				log.warn("table column names custom configuration problem", e);
  723   				continue;
  724   			}
  725   			int index = names.indexOf(name);
  726   			
  727   			String element = null;
  728   			try {
  729   				element = (String) names.get(index);
  730   			} catch(ArrayIndexOutOfBoundsException e) {
  731   				log.warn("table column names custom configuration problem", e);
  732   				continue;
  733   			}
  734   			names.remove(index);
  735   			names.insertElementAt(element, i);
  736   			fTable.moveColumn(index, i);
  737   			
  738   			
  739   			int columnWidth = fPropManager.getIntProperty("column" + i + ".width", 200);
  740   			TableColumn column = columnModel.getColumn(i);
  741   			column.setPreferredWidth(columnWidth);
  742   		}
  743   		
  744   		// Read Main Window size and position
  745   		int x = fPropManager.getIntProperty("frame.x", 0);
  746   		int y = fPropManager.getIntProperty("frame.y", 0);
  747   		int width = fPropManager.getIntProperty("frame.width", WIDTH);
  748   		int height = fPropManager.getIntProperty("frame.height", HEIGHT);
  749   		int tolerance = 5; 
  750   		Rectangle win = new Rectangle(x, y, width, height);
  751   		Rectangle screen = new Rectangle(new Point(-tolerance, -tolerance), 
  752   								Toolkit.getDefaultToolkit().getScreenSize());
  753   		screen.grow(tolerance * 2, tolerance * 2);
  754   		if (screen.contains(win))
  755   			this.setBounds(win);
  756   		else {
  757   			this.setSize(WIDTH, HEIGHT);
  758   			this.setLocation(0, 0);
  759   		}
  760   		
  761   		// Read last extraction directory
  762   		String path = fPropManager.getProperty("extract.lastFolder");
  763   		if (path != null)
  764   			fExtractDir = new File(path);
  765   		else
  766   			fExtractDir = Utils.getCurrentDir();
  767   		
  768   		// Sorting column
  769   		String column = fPropManager.getProperty("sorting.column");
  770   		if (column != null) {
  771   			int index = names.indexOf(column);
  772   			fTableModel.sortByColumnRefresh(index);
  773   		}
  774   		
  775   		// Extraction path history
  776   		fPathList = new Vector();
  777   		String firstPath = fPropManager.getProperty("extract.path0");
  778   		if ((firstPath != null) && (firstPath.length() > 0)) {
  779   			for (int i = 0; i < fMaxExtractHistory; i++) {
  780   				path = fPropManager.getProperty("extract.path" + i);
  781   				if (path == null) break;
  782   				//log.debug("Add to extract history: " + path);
  783   				fPathList.add(i, path);
  784   			}
  785   		} else
  786   			fPathList.add(fExtractDir.toString());
  787   			
  788   		// add last open archives history
  789   		path = fPropManager.getProperty("file.path0");
  790   		int size = fFileHistory.size();
  791   		if ((path != null) && (path.length() > 0)) {
  792   			for (int i = 0; i < size; i++) {
  793   				path = fPropManager.getProperty("file.path" + i);
  794   				if (path == null) break;
  795   				fFileHistory.add(path, true);
  796   			}
  797   		}
  798   		
  799   	}
  800   	
  801   	
  802   	
  803   	/**
  804   	*	Load small image by given package path.
  805   	*/
  806   	private ImageIcon loadImage(String aImage) {
  807   		URL url = getClass().getResource(aImage);
  808   		return new ImageIcon(url);
  809   	}
  810   	
  811   	
  812   	
  813   	/**
  814   	*	Set message to left or to right side of statusbar at the bottom 
  815   	*	of the application.
  816   	*	Use SwingConstants.RIGHT, SwingConstants.LEFT
  817   	*/
  818   	private void setStatusMessage(String aMessage, int aSide) {
  819   		switch(aSide) {
  820   			case SwingConstants.RIGHT: {
  821   				fRightStatusLabel.setText(aMessage);
  822   				break;
  823   			}
  824   			case SwingConstants.LEFT: {
  825   				fLeftStatusLabel.setText(aMessage);
  826   				break;
  827   			}
  828   		}
  829   	}
  830   	
  831   	
  832   	
  833   	/**
  834   	*	Send message to right side of status bar with default text.
  835   	*	Example: Total 15 files, 134KB
  836   	*/
  837   	private void setDefaultRightStatusMessage() {
  838   		setStatusMessage(	strTotal +
  839   							fTableModel.getRowCount() + " " +
  840   							strFiles +
  841   							fSupport.getTotalUncompressedSize() / 1024 + "KB",
  842   							SwingConstants.RIGHT);
  843   	}
  844   	
  845   	
  846   	
  847   	/**
  848   	*	Send message to left side of status bar with default text.
  849   	*	Example: Selected 15 files, 134KB
  850   	*/
  851   	private void setDefaultLeftStatusMessage() {
  852   		long size = fSupport.getItemsUncompressedSize(fTable.getSelectedRows());
  853   		String composed;
  854   		
  855   		if (size < 1024) 
  856   			composed = 	strSelected +
  857   						fTable.getSelectedRowCount() + " " +
  858   						strFiles +
  859   						size + strBytes;
  860   		else
  861   			composed = 	strSelected +
  862   						fTable.getSelectedRowCount() + " " +
  863   						strFiles +
  864   						size / 1024 + "KB";
  865   		
  866   		setStatusMessage(composed, SwingConstants.LEFT);
  867   	}
  868   	
  869   	
  870   	
  871   	private void showLogDialog() {
  872   		LogDialog dialog = new LogDialog(Main.this, true);
  873   		dialog.setText(fOutputManager.getOutput());
  874   		dialog.show();
  875   	}
  876   	
  877   	
  878   	
  879   	/**
  880   	*	This method show monitor dialog in separate thread but only one
  881   	*	thread for monitor is possible in same time.
  882   	*/
  883   	public synchronized void showMonitor() {
  884   		this.getGlassPane().setVisible(true);
  885   		fMonitor.show();
  886   	}
  887   	
  888   	
  889   	
  890   	/**
  891   	*	This method hide monitor dialog, terminate and kill monitor thread.
  892   	*/
  893   	public synchronized void hideMonitor() {
  894   		this.getGlassPane().setVisible(false);
  895   		fMonitor.dispose();
  896   	}
  897   	
  898   	
  899   	
  900   	/**
  901   	*	Return reference to current operation monitor.
  902   	*/
  903   	public NeonMonitor getMonitor() {
  904   		return fMonitor;
  905   	}
  906   	
  907   	
  908   	
  909   	/**
  910   	*	Application startup.
  911   	*/
  912   	public static void main(String[] args) {
  913   		configLog4j();
  914   		Main main = new Main();
  915   		main.show();
  916   	}
  917   	
  918   	
  919   	
  920   	/**
  921   	*	Configure Apache Log4j by config file
  922   	*	If config file exists in project home directory then enable logging
  923   	*	by given configuration.
  924   	*	If config file not exists then disable all logging system.
  925   	*/
  926   	private static void configLog4j() {
  927   		File conf = new File(Utils.getAppHomeDir(), "log4j.conf");
  928   		FileInputStream input = null;
  929   		Properties log4jProps = new Properties();
  930   		try {
  931   			input = new FileInputStream(conf);
  932   			log4jProps.load(input);
  933   		} catch (Exception e) {
  934   			/* log4j config missing. and all tracing disabled */
  935   			BasicConfigurator.configure();
  936   			Category.getDefaultHierarchy().disableAll();
  937   		}
  938   		
  939   		PropertyConfigurator.configure(log4jProps);
  940   	}
  941   	
  942   	
  943   	
  944   	/**
  945   	*	Customize TableModel befavior.
  946   	*/
  947   	private final class ArchiveTableModel extends AbstractTableModel {
  948   		
  949   		private int fSortCol = 0;	// column
  950   		private boolean fSortAsc = true;	// direction
  951   		
  952   		ArchiveTableModel() {
  953   			super();
  954   		}
  955   		
  956   		/**
  957   		*	Awlays return false and disable cell edit possibilities.
  958   		*/
  959   		public boolean isCellEditable(int aRow, int aCol) {
  960   			return false;
  961   		}
  962   		
  963   		public int getRowCount() {
  964   			return fTableData.size();
  965   		}
  966   	  	
  967   		public int getColumnCount() {
  968   			return fColumnNames.size();
  969   		}
  970     		
  971   		public Object getValueAt(int row, int column) {
  972   			Vector rowVector = (Vector) fTableData.elementAt(row);
  973   			return rowVector.elementAt(column);
  974   		}
  975   		
  976   		public String getColumnName(int column) {
  977   			String str = super.getColumnName(column);
  978   			String result = null;
  979   			if (fColumnNames == null || fColumnNames.size() <= column) {
  980   				result = str;
  981   			}
  982   			Object id = fColumnNames.elementAt(column);
  983   			if (id == null) {
  984   				result = str;
  985   			}
  986   			else {
  987   				str = id.toString();
  988   				result = str;
  989   			}
  990   			
  991   			if (column == fSortCol) result += fSortAsc ? " >>" : " <<";
  992   			
  993   			return result;
  994       	}
  995   		
  996   		/**
  997   		*	Check for table row selection.
  998   		*	@return true if has selected rows on the table; false otherwise
  999   		*/
 1000   		public boolean isSelectedRow() {
 1001   			return fTable.getSelectedRowCount() > 0;
 1002   		}
 1003   		
 1004   		
 1005   		
 1006   		/**
 1007   		*	Check for table data.
 1008   		*	@return true if table is empty (without row data); false otherwise
 1009   		*/
 1010   		public boolean isTableEmpty() {
 1011   			return fTable.getRowCount() < 1;
 1012   		}
 1013   		
 1014   		
 1015   		
 1016   		/**
 1017   		*	Default ascending sort by first column
 1018   		*/
 1019   		public void setDefaultSorting() {
 1020   			Collections.sort(fTableData, new ArchiveComparator(fSortCol
 1021   			, fSortAsc));
 1022   		}
 1023   		
 1024   		
 1025   		
 1026   		/**
 1027   		*	Sort by given column index. (Without JTable refreshing).
 1028   		*/
 1029   		public void sortByColumn(int aIndex) {
 1030   			Collections.sort(fTableData, new ArchiveComparator(aIndex
 1031   			, fSortAsc));
 1032   		}
 1033   		
 1034   		
 1035   		
 1036   		/**
 1037   		*	Sort by given column index and refresh JTable.
 1038   		*/
 1039   		public void sortByColumnRefresh(int aIndex) {
 1040   			sorting(aIndex);
 1041   		}
 1042   		
 1043   		
 1044   		
 1045   		/**
 1046   		*	Return index of sorted column.
 1047   		*/
 1048   		public int getSortingColumn() {
 1049   			return fSortCol;
 1050   		}
 1051   		
 1052   		
 1053   		
 1054   		private void sorting(int aColumnIndex) {
 1055   			TableColumnModel colModel = fTable.getColumnModel();
 1056   			int columnModelIndex = aColumnIndex;
 1057   			int modelIndex = colModel.getColumn(columnModelIndex).getModelIndex();
 1058   			if (modelIndex < 0)
 1059   				return;
 1060   			if (fSortCol == modelIndex)
 1061   				fSortAsc = !fSortAsc;
 1062   			else
 1063   				fSortCol = modelIndex;
 1064   			
 1065   			for(int i = 0; i < fColumnNames.size(); i++) {
 1066   				TableColumn column = colModel.getColumn(i);
 1067   				column.setHeaderValue(fTableModel.getColumnName(column.getModelIndex()));
 1068   			}
 1069   			
 1070   			fTable.getTableHeader().repaint();
 1071   			Collections.sort(fTableData,
 1072   				new ArchiveComparator(modelIndex, fSortAsc));
 1073   			fTable.tableChanged(new TableModelEvent(fTableModel));
 1074   			fTable.repaint();
 1075   		}
 1076   		
 1077   		
 1078   		
 1079   		/**
 1080   		*	If mouse clicked on column header then sort column or 
 1081   		*	reverce order of sort.
 1082   		*/
 1083   		private final class ColumnListener extends MouseAdapter {
 1084   			
 1085   			public ColumnListener() {
 1086   //				log.debug("ColumnListener created");
 1087   			}
 1088   			
 1089   			public void mouseClicked(MouseEvent e) {
 1090   				TableColumnModel colModel = fTable.getColumnModel();
 1091   				int columnIndex = colModel.getColumnIndexAtX(e.getX());
 1092   				sorting(columnIndex);
 1093   			}
 1094   		}
 1095   		
 1096   		
 1097   		
 1098   		/**
 1099   		*	Comparator for archive data objects.
 1100   		*	Uses current sort column and direction to determine
 1101   		*	what to compare.
 1102   		*/
 1103   		private final class ArchiveComparator implements Comparator {
 1104   			
 1105   			private int fSortCol;
 1106   			private boolean fSortAsc;
 1107   			
 1108   			DateFormat fDateFormat = DateFormat.getDateInstance();
 1109   			
 1110   			public ArchiveComparator(int aSortCol, boolean aSortAsc) {
 1111   				fSortCol = aSortCol;
 1112   				fSortAsc = aSortAsc;
 1113   			}
 1114   			
 1115   			public int compare(Object aObject1, Object aObject2) {
 1116   				Vector v1 = (Vector) aObject1;
 1117   				Vector v2 = (Vector) aObject2;
 1118   				
 1119   				int result = 0;
 1120   				
 1121   				switch(fSortCol) {
 1122   					// file name
 1123   					case 0: {
 1124   						String str1 = (String) v1.get(fSortCol);
 1125   						String str2 = (String) v2.get(fSortCol);
 1126   						result = str1.compareTo(str2);
 1127   						break;
 1128   					}
 1129   					// file type
 1130   					case 1: {
 1131   						String str1 = (String) v1.get(fSortCol);
 1132   						String str2 = (String) v2.get(fSortCol);
 1133   						result = str1.compareTo(str2);
 1134   						break;
 1135   					}
 1136   					// date
 1137   					case 2: {
 1138   						try {
 1139   							Date date1 = fDateFormat.parse((String) v1.get(fSortCol));
 1140   							Date date2 = fDateFormat.parse((String) v2.get(fSortCol));
 1141   							result = date1.compareTo(date2);
 1142   						} catch (ParseException e) {
 1143   							log.error("Invalid date while sorting", e);
 1144   							System.err.println(e);
 1145   						}
 1146   						break;
 1147   					}
 1148   					// size
 1149   					case 3: {
 1150   						double double1 = Double.parseDouble((String) v1.get(fSortCol));
 1151   						double double2 = Double.parseDouble((String) v2.get(fSortCol));
 1152   						result = double1 < double2 ? -1 : (double1 > double2 ? 1 : 0);
 1153   						break;
 1154   					}
 1155   					// ratio %%%%
 1156   					case 4: {
 1157   						String str1 = ((String) v1.get(fSortCol)).replace('%', ' ');
 1158   						String str2 = ((String) v2.get(fSortCol)).replace('%', ' ');
 1159   						double double1 = Double.parseDouble(str1);
 1160   						double double2 = Double.parseDouble(str2);
 1161   						result = double1 < double2 ? -1 : (double1 > double2 ? 1 : 0);
 1162   						break;
 1163   					}
 1164   					// packed size
 1165   					case 5: {
 1166   						double double1 = Double.parseDouble((String) v1.get(fSortCol));
 1167   						double double2 = Double.parseDouble((String) v2.get(fSortCol));
 1168   						result = double1 < double2 ? -1 : (double1 > double2 ? 1 : 0);
 1169   						break;
 1170   					}
 1171   					// CRC
 1172   					case 6: {
 1173   						String str1 = (String) v1.get(fSortCol);
 1174   						String str2 = (String) v2.get(fSortCol);
 1175   						result = str1.compareTo(str2);
 1176   						break;
 1177   					}
 1178   					// path
 1179   					case 7: {
 1180   						String str1 = (String) v1.get(fSortCol);
 1181   						String str2 = (String) v2.get(fSortCol);
 1182   						result = str1.compareTo(str2);
 1183   						break;
 1184   					}
 1185   				}
 1186   				if (!fSortAsc)
 1187   					result = -result;
 1188   				return result;
 1189   			}
 1190   			
 1191   			public boolean equals(Object aObject) {
 1192   				return false;
 1193   			}
 1194   		}
 1195   	}
 1196   	
 1197   	
 1198   	
 1199   	/**
 1200   	*	Custom cell renderer behaviour - never draw selection.
 1201   	*/
 1202   	private final class ArchiveTableCellRenderer extends DefaultTableCellRenderer {
 1203   		
 1204   		public Component getTableCellRendererComponent(	JTable table,
 1205                        									Object value,
 1206                        									boolean isSelected,
 1207                        									boolean hasFocus,
 1208                        									int row,
 1209                        									int column) {
 1210   		return super.getTableCellRendererComponent(	table,
 1211   													value,
 1212   													false,
 1213   													false,
 1214                      									row,
 1215                        								column);
 1216   		}
 1217   	}
 1218   	
 1219   	
 1220   	
 1221   	/**
 1222   	*	Extends JTable and disable selection of all columns except "Names".
 1223   	*/
 1224   	public final class ArchiveTable extends JTable
 1225   		implements DropTargetListener {
 1226   		
 1227   		private DropTarget fDropTarget = new DropTarget(this, this);
 1228   		
 1229   		public ArchiveTable(Vector aRowData, Vector aColumnNames) {
 1230   			super(aRowData, aColumnNames);
 1231   		}
 1232   		
 1233   		
 1234   		
 1235   		public ArchiveTable(TableModel tm) {
 1236   			super(tm);
 1237   		}
 1238   		
 1239   		
 1240   		
 1241   		public ArchiveTable() {
 1242   			super();
 1243   		}
 1244   		
 1245   		
 1246   		
 1247   		protected void processMouseEvent(MouseEvent e) {
 1248   			int view = this.columnAtPoint(new Point(e.getX(), e.getY()));
 1249   			int index = this.convertColumnIndexToModel(view);
 1250   			TableColumn column = this.getColumn("name");
 1251   			int nameIndex = column.getModelIndex();
 1252   			if (index != nameIndex) return;
 1253   			if (e.getID() == MouseEvent.MOUSE_CLICKED || e.getID() == MouseEvent.MOUSE_PRESSED) {
 1254   			}
 1255   			super.processMouseEvent(e);
 1256   		}
 1257   		
 1258   		
 1259   		
 1260   		protected void processMouseMotionEvent(MouseEvent e) {
 1261   			int view = this.columnAtPoint(new Point(e.getX(), e.getY()));
 1262   			int index = this.convertColumnIndexToModel(view);
 1263   			TableColumn column = this.getColumn("name");
 1264   			int nameIndex = column.getModelIndex();
 1265   			if (index != nameIndex) return;
 1266   			
 1267   			super.processMouseMotionEvent(e);
 1268   		}
 1269   		
 1270   		
 1271   		
 1272   		public void dragEnter(DropTargetDragEvent e) {
 1273   		}
 1274   		
 1275   		
 1276   		
 1277   		public void dragDropEnd(DragSourceDropEvent e) {
 1278   //			log.debug("dragDropEnd() " + e.toString());
 1279   //			log.debug("isDropSuccess: " + e.getDropSuccess());
 1280   		}
 1281   		
 1282   		
 1283   		
 1284   		public void dragOver(DropTargetDragEvent e) {
 1285   		}
 1286   		
 1287   		
 1288   		
 1289   		public void dragExit(DropTargetEvent e) {
 1290   		}
 1291   		
 1292   		
 1293   		
 1294   		public void dropActionChanged(DropTargetDragEvent e) {
 1295   		}
 1296   		
 1297   		
 1298   		
 1299   		/**
 1300   		*	Provide Native to JTable drag and drop operation.
 1301   		*/
 1302   		public synchronized void drop(DropTargetDropEvent e) {
 1303   			log.debug("drop() " + e.toString());
 1304   			try {
 1305   				Transferable tr = e.getTransferable();
 1306   				if (tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
 1307   					e.acceptDrop(DnDConstants.ACTION_COPY);
 1308   					java.util.List files = (java.util.List) 
 1309   						tr.getTransferData(DataFlavor.javaFileListFlavor);
 1310   					final File[] fileArray = new File[files.size()];
 1311   					Iterator iterator = files.iterator();
 1312   					for (int i = 0; i < files.size(); i++) {
 1313   						File file = (File) files.get(i);
 1314   						log.debug("droped file: " + file.toString());
 1315   						fileArray[i] = file;
 1316   					}
 1317   					e.getDropTargetContext().dropComplete(true);
 1318   					
 1319   					// check if droped file is supported archive; if this is
 1320   					// true then open vs. add
 1321   					File firstFile = fileArray[0];
 1322   					String extension = Utils.getExtension(firstFile.toString());
 1323   					Arrays.sort(ArchiveSupport.TYPES);
 1324   					int result = Arrays.binarySearch(ArchiveSupport.TYPES, extension.toLowerCase());
 1325   					log.debug("Search result: " + result);
 1326   					if (result >= 0) {
 1327   						Main.this.refreshTable(firstFile);
 1328   						return;
 1329   					}
 1330   					//
 1331   					
 1332   					final File currentDir = searchCurrentDir(fileArray);
 1333   					log.debug("source dir: " + currentDir.toString());
 1334   					DragAddRunnable dragAdd = 
 1335   						new DragAddRunnable(fileArray,
 1336   											currentDir,
 1337   											fSupport.getCurrentOpen(),
 1338   											null,
 1339   											AddDialog.ADD_ACTION,
 1340   											AddDialog.COMPRESSION_9,
 1341   											true,
 1342   											false);
 1343   					Thread thread = new Thread(dragAdd);
 1344   					thread.start();
 1345   				} else
 1346   					e.rejectDrop();
 1347   			} catch (IOException exc) {
 1348   				e.rejectDrop();
 1349   				log.info("drop() exception", exc);
 1350   			} catch (UnsupportedFlavorException exc) {
 1351   				e.rejectDrop();
 1352   				log.info("drop() exception", exc);
 1353   			}
 1354   
 1355   		}
 1356   		
 1357   		
 1358   		
 1359   		/**
 1360   		*	This method looking for current directory in DnD file list.
 1361   		*	Of course the smaller dir is the current.
 1362   		*/
 1363   		private File searchCurrentDir(File[] aFileList) {
 1364   			File smaller = aFileList[0];
 1365   			for (int i = 1; i < aFileList.length; i++) {
 1366   				File file = aFileList[i];
 1367   				int result = file.compareTo(smaller);
 1368   				if (result < 0) smaller = file;
 1369   			}
 1370   			
 1371   			if (!smaller.isDirectory()) 
 1372   				return smaller.getParentFile();
 1373   			else
 1374   				return smaller;
 1375   		}
 1376   		
 1377   		
 1378   		
 1379   		private final class DragAddRunnable implements Runnable {
 1380   			
 1381   			private File[] fFileList;
 1382   			private File fCurrentDir;
 1383   			private File fArchive;
 1384   			private String fFilter;
 1385   			private int fAction;
 1386   			private int fCompression;
 1387   			private boolean fSubfolders;
 1388   			private boolean fPathinfo;
 1389   			
 1390   			DragAddRunnable(File[] aFileList,
 1391   							File aCurrentDir,
 1392   							File aArchive,
 1393   							String aFilter,
 1394   							int aAction,
 1395   							int aCompression,
 1396   							boolean aSubfolders,
 1397   							boolean aPathinfo) {
 1398   				
 1399   				fFileList = aFileList;
 1400   				fCurrentDir = aCurrentDir;
 1401   				fArchive = aArchive;
 1402   				fFilter = aFilter;
 1403   				fAction = aAction;
 1404   				fCompression = aCompression;
 1405   				fSubfolders = aSubfolders;
 1406   				fPathinfo = aPathinfo;
 1407   			}
 1408   			
 1409   			public void run() {
 1410   				fSupport.add(	fFileList,
 1411   								fCurrentDir,
 1412   								fArchive,
 1413   								fFilter,
 1414   								fAction,
 1415   								fCompression,
 1416   								fSubfolders,
 1417   								fPathinfo);
 1418   				refreshTable(fSupport.getCurrentOpen());
 1419   			}
 1420   			
 1421   		}
 1422   		
 1423   		
 1424   		
 1425   	} // End of ArchiveTable
 1426   	
 1427   	
 1428   	
 1429   	/**
 1430   	*	Viewport component that accept drop operations.
 1431   	*	Support dnd and open of file from native to the scroll pane viewport.
 1432   	*/
 1433   	private final class ViewportDropTargetListener extends DropTarget implements
 1434   	DropTargetListener {
 1435   		
 1436   		ViewportDropTargetListener() {
 1437   		}
 1438   		
 1439   		public void dragEnter(DropTargetDragEvent e) {
 1440   		}
 1441   		
 1442   		public void dragExit(DropTargetEvent e) {
 1443   		}
 1444   		
 1445   		public void dragOver(DropTargetDragEvent e) {
 1446   		}
 1447   		
 1448   		public void drop(DropTargetDropEvent e) {
 1449   			try {
 1450   				Transferable tr = e.getTransferable();
 1451   				if (tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
 1452   					e.acceptDrop(DnDConstants.ACTION_COPY);
 1453   					java.util.List files = (java.util.List) 
 1454   						tr.getTransferData(DataFlavor.javaFileListFlavor);
 1455   					File file = (File) files.get(0);
 1456   					e.getDropTargetContext().dropComplete(true);
 1457   					Main.this.refreshTable(file);
 1458   				} else
 1459   					e.rejectDrop();
 1460   			} catch (IOException exc) {
 1461   				e.rejectDrop();
 1462   				log.info("drop() exception", exc);
 1463   			} catch (UnsupportedFlavorException exc) {
 1464   				e.rejectDrop();
 1465   				log.info("drop() exception", exc);
 1466   			}
 1467   		}
 1468   		
 1469   		public void dropActionChanged(DropTargetDragEvent e) {
 1470   		}
 1471   	}
 1472   	
 1473   	
 1474   	
 1475   	/**
 1476   	*	Listener for mouse events linked to Component(for test needs).
 1477   	*/
 1478   	private final class TestMouseListener implements MouseListener {
 1479   		
 1480   		TestMouseListener() {
 1481   		}
 1482   		
 1483   		public void mousePressed(MouseEvent e) {
 1484   			log.debug("Mouse Pressed");
 1485   		}
 1486   	
 1487   		public void mouseReleased(MouseEvent e) {
 1488   		}
 1489   	
 1490   		public void mouseEntered(MouseEvent e) {
 1491   		}
 1492   	
 1493   		public void mouseExited(MouseEvent e) {
 1494   		}
 1495   	
 1496   		public void mouseClicked(MouseEvent e) {
 1497   		}
 1498   	}
 1499   	
 1500   	
 1501   	
 1502   	/**
 1503   	*	Options menu listener.
 1504   	*/
 1505   	private final class OptionsMenuListener implements MenuListener {
 1506   		
 1507   		private OptionsMenuListener() {
 1508   		}
 1509   		
 1510   		public void menuCanceled(MenuEvent e) {
 1511   		}
 1512   		
 1513   		public void menuDeselected(MenuEvent e) {
 1514   		}
 1515   		
 1516   		public void menuSelected(MenuEvent e) {
 1517   			lastOutputAction.setEnabled(!fOutputManager.isEmpty());
 1518   		}
 1519   		
 1520    	}
 1521   	
 1522   	
 1523   	
 1524   	private final class RecentFilesMenuListener implements MenuListener {
 1525   		
 1526   		private RecentFilesMenuListener() {
 1527   		}
 1528   		
 1529   		public void menuCanceled(MenuEvent e) {
 1530   		}
 1531   		
 1532   		public void menuDeselected(MenuEvent e) {
 1533   		}
 1534   		
 1535   		public void menuSelected(MenuEvent e) {
 1536   			fFileHistory.drawToMenu();
 1537   		}
 1538   	}
 1539   	
 1540   	
 1541   	
 1542   	/**
 1543   	*	Sorting menu listener.
 1544   	*/
 1545   	private final class SortingMenuListener implements MenuListener {
 1546   		
 1547   		private SortingMenuListener() {
 1548   		}
 1549   		
 1550   		public void menuCanceled(MenuEvent e) {
 1551   		}
 1552   		
 1553   		public void menuDeselected(MenuEvent e) {
 1554   		}
 1555   		
 1556   		public void menuSelected(MenuEvent e) {
 1557   			JMenu menu = (JMenu) e.getSource();
 1558   			ArrayList list = new ArrayList(8);
 1559   			list.add("Name");
 1560   			list.add("Type");
 1561   			list.add("Modified");
 1562   			list.add("Size");
 1563   			list.add("Ratio");
 1564   			list.add("Packed");
 1565   			list.add("CRC");
 1566   			list.add("Path");
 1567   
 1568   			String sorted = (String)
 1569   				fColumnNames.get(fTableModel.getSortingColumn());
 1570   				
 1571   			int index = list.indexOf(sorted);
 1572   			
 1573   			JRadioButtonMenuItem subMenu = (JRadioButtonMenuItem) menu.getMenuComponent(index);
 1574   			subMenu.setSelected(true);
 1575   		}
 1576   		
 1577   	}
 1578   	
 1579   	
 1580   	
 1581   	private final class RecentFilesAction extends AbstractAction {
 1582   		RecentFilesAction() {
 1583   			super();
 1584   		}
 1585   		
 1586   		public void actionPerformed(ActionEvent e) {
 1587   			JMenuItem item = (JMenuItem) e.getSource();
 1588   			String filename = item.getText();
 1589   			File file = new File(filename);
 1590   			fFileHistory.add(filename, false);
 1591   			refreshTable(file);
 1592   		}
 1593   	}
 1594   	
 1595   	
 1596   	
 1597   	/**
 1598   	*	Exit menu action.
 1599   	*/
 1600   	private final class ExitAction extends AbstractAction {
 1601   		ExitAction() {
 1602   			super(fResources.getString("key.menu.exit"));
 1603   		}
 1604   		
 1605   		public void actionPerformed(ActionEvent aEvent) {
 1606   			Main.this.appClosing(new WindowEvent(Main.this, 0));
 1607   		}
 1608   	}
 1609   	
 1610   	
 1611   	
 1612   	/**
 1613   	*	Sorting menu action.
 1614   	*/
 1615   	private final class SortingAction extends AbstractAction {
 1616   		
 1617   		SortingAction() {
 1618   		}
 1619   		
 1620   		public void actionPerformed(ActionEvent aEvent) {
 1621   			JRadioButtonMenuItem menu = (JRadioButtonMenuItem) aEvent.getSource();
 1622   			String command = menu.getActionCommand();
 1623   			int index = fColumnsMaped.indexOf(command);
 1624   			fTableModel.sortByColumnRefresh(index);
 1625   		}
 1626   	}
 1627   	
 1628   	
 1629   	
 1630   	/**
 1631   	*	Open Archive menu action
 1632   	*/
 1633   	private final class OpenArchiveAction extends AbstractAction {
 1634   		OpenArchiveAction() {
 1635   			super(fResources.getString("key.menu.open_archive") + "...");
 1636   		}
 1637   		
 1638   		public void actionPerformed(ActionEvent aEvent) {
 1639   			OpenRunnable runnable = new OpenRunnable();
 1640   			Thread thread = new Thread(runnable);
 1641   			thread.start();
 1642   		}
 1643   	}
 1644   	
 1645   	
 1646   	
 1647   	/**
 1648   	*	New Archive menu action
 1649   	*/
 1650   	private final class NewArchiveAction extends AbstractAction {
 1651   		NewArchiveAction() {
 1652   			super(fResources.getString("key.menu.new_archive") + "...");
 1653   		}
 1654   		
 1655   		public void actionPerformed(ActionEvent aEvent) {
 1656   			JFileChooser chooser = new JFileChooser();
 1657   			chooser.setDialogTitle(fResources.getString("key.title.new_archive"));
 1658   			NeonFileFilter filter = new NeonFileFilter();
 1659   			filter.addExtension("zip");
 1660   			filter.setDescription("ZIP " + fResources.getString("key.title.archives"));
 1661   			chooser.setFileFilter(filter);
 1662   			JPanel accessory = new JPanel();
 1663   			JCheckBox checkbox = new JCheckBox(fResources.getString("key.checkbox.add_dialog"));
 1664   			accessory.add(checkbox);
 1665   			chooser.setAccessory(accessory);
 1666   			int result = chooser.showDialog(Main.this, fResources.getString("key.button.new_archive"));
 1667   			if (result == JFileChooser.APPROVE_OPTION) {
 1668   				File file = chooser.getSelectedFile();
 1669   				String newfile = Utils.addExtension(file.toString(), "zip");
 1670   				fSupport.create(new File(newfile));
 1671   				setTitle(TITLE + " - " + Utils.removePath(newfile));
 1672   				// if add dialog checkbox is checked
 1673   				if (checkbox.isSelected()) {
 1674   					new AddAction().actionPerformed(new ActionEvent(this, 0, "invoke addactiom"));
 1675   				}
 1676   			}
 1677   		}
 1678   	}
 1679   	
 1680   	
 1681   	
 1682   	/**
 1683   	*	Close archive menu action
 1684   	*/
 1685   	private final class CloseArchiveAction extends AbstractAction {
 1686   		CloseArchiveAction() {
 1687   			super(fResources.getString("key.menu.close_archive"));
 1688   		}
 1689   		
 1690   		public void actionPerformed(ActionEvent aEvent) {
 1691   			fSupport.close();
 1692   			fTableData.clear();
 1693   			fTable.updateUI();
 1694   			setTitle(TITLE);
 1695   		}
 1696   	}
 1697   	
 1698   	
 1699   	
 1700   	/**
 1701   	*	Add menu action
 1702   	*/
 1703   	private final class AddAction extends AbstractAction {
 1704   		AddAction() {
 1705   			super(fResources.getString("key.menu.add") + "...");
 1706   		}
 1707   		
 1708   		public void actionPerformed(ActionEvent aEvent) {
 1709   			AddRunnable runnable = new AddRunnable();
 1710   			Thread thread = new Thread(runnable);
 1711   			thread.start();
 1712   		}
 1713   	}
 1714   	
 1715   	
 1716   	
 1717   	/**
 1718   	*	Delete menu action
 1719   	*/
 1720   	private final class DeleteAction extends AbstractAction {
 1721   		DeleteAction() {
 1722   			super(fResources.getString("key.menu.delete") + "...");
 1723   		}
 1724   		
 1725   		public void actionPerformed(ActionEvent aEvent) {
 1726   			DeleteRunnable runnable = new DeleteRunnable();
 1727   			Thread thread = new Thread(runnable);
 1728   			thread.start();
 1729   		}
 1730   	}
 1731   	
 1732   	
 1733   	
 1734   	/**
 1735   	*	Extract menu action
 1736   	*/
 1737   	private final class ExtractAction extends AbstractAction {
 1738   		ExtractAction() {
 1739   			super(fResources.getString("key.menu.extract") + "...");
 1740   		}
 1741   		
 1742   		public void actionPerformed(ActionEvent aEvent) {
 1743   			ExtractRunnable runnable = new ExtractRunnable();
 1744   			Thread thread = new Thread(runnable);
 1745   			thread.start();
 1746   		}
 1747   		
 1748   		
 1749   	}
 1750   	
 1751   	
 1752   	
 1753   	/**
 1754   	*	Select All menu action.
 1755   	*/
 1756   	public final class SelectAllAction extends AbstractAction {
 1757   		
 1758   		SelectAllAction() {
 1759   			super(fResources.getString("key.menu.select_all"));
 1760   		}
 1761   		
 1762   		public void actionPerformed(ActionEvent aEvent) {
 1763   			if (fTableModel.isTableEmpty()) return;
 1764   			fTable.selectAll();
 1765   		}
 1766   		
 1767   	}
 1768   	
 1769   	
 1770   	
 1771   	/**
 1772   	*	Invert selection action.
 1773   	*/
 1774   	public final class InvertSelectionAction extends AbstractAction {
 1775   		
 1776   		InvertSelectionAction() {
 1777   			super(fResources.getString("key.menu.invert_selection"));
 1778   		}
 1779   		
 1780   		public void actionPerformed(ActionEvent aEvent) {
 1781   			int total_count = fTable.getRowCount();
 1782   			ArrayList selected = new ArrayList(total_count);
 1783   			ArrayList unselected = new ArrayList(total_count);
 1784   			// sort
 1785   			for (int i = 0; i < total_count; i++) {
 1786   				boolean selection = fTable.isRowSelected(i);
 1787   				if (selection)
 1788   					selected.add(new Integer(i));
 1789   				else
 1790   					unselected.add(new Integer(i));
 1791   			}
 1792   			
 1793   			// deselect selection
 1794   			for (int i = 0; i < selected.size(); i++) {
 1795   				int index = ((Integer) selected.get(i)).intValue();
 1796   				fTable.removeRowSelectionInterval(index, index);
 1797   			}
 1798   			
 1799   			// select unselected
 1800   			for (int i = 0; i < unselected.size(); i++) {
 1801   				int index = ((Integer) unselected.get(i)).intValue();
 1802   				fTable.addRowSelectionInterval(index, index);
 1803   			}
 1804   		}
 1805   		
 1806   	}
 1807   	
 1808   	
 1809   	
 1810   	/**
 1811   	*	View Last Output action.
 1812   	*/
 1813   	public final class LastOutputAction extends AbstractAction {
 1814   		
 1815   		LastOutputAction() {
 1816   			super(fResources.getString("key.menu.view_last_output") + "...");
 1817   		}
 1818   		
 1819   		public void actionPerformed(ActionEvent e) {
 1820   			showLogDialog();
 1821   		}
 1822    	}
 1823   	
 1824   	
 1825   	
 1826   	private final class LastOpenHistoryAction extends AbstractAction {
 1827   		
 1828   		LastOpenHistoryAction() {
 1829   			super();
 1830   		}
 1831   		
 1832   		public void actionPerformed(ActionEvent e) {
 1833   			
 1834   		}
 1835   		
 1836   	}
 1837   	
 1838   	
 1839   	
 1840   	/**
 1841   	*	Test the integrity of current open archive.
 1842   	*/
 1843   	private final class TestIntegrityAction extends AbstractAction {
 1844   		
 1845   		TestIntegrityAction() {
 1846   			super(fResources.getString("key.menu.test_integrity"));
 1847   		}
 1848   		
 1849   		public void actionPerformed(ActionEvent e) {
 1850   			TestIntegrityRunnable runnable = new TestIntegrityRunnable();
 1851   			Thread thread = new Thread(runnable);
 1852   			thread.start();
 1853   		}
 1854   		
 1855   	}
 1856   	
 1857   	
 1858   	
 1859   	/**
 1860   	*	Extract action executed in separate thread
 1861   	*/
 1862   	private final class ExtractRunnable implements Runnable {
 1863   		
 1864   		ExtractRunnable() {
 1865   		}
 1866   		
 1867   		public void run() {
 1868   			if (!Utils.isFileExists(fExtractDir.toString()))
 1869   			fExtractDir = Utils.getCurrentDir();
 1870   			ExtractDialog extract = new ExtractDialog(Main.this, true, 
 1871   				fExtractDir, fPathList);
 1872   			extract.setSelectedFilesEnabled(fTableModel.isSelectedRow());
 1873   			extract.setSelectedFilesSelected(fTableModel.isSelectedRow());
 1874   			extract.setAllFilesSelected(!fTableModel.isSelectedRow());
 1875   			extract.setUseFolder(true);
 1876   			extract.show();
 1877   			
 1878   			// user approved extraction
 1879   			if (extract.isApproved()) {
 1880   				// extraction path
 1881   				fExtractDir = extract.getExtractionPath();
 1882   				File destDir = extract.getExtractionPath();
 1883   				
 1884   				if (!fPathList.contains(fExtractDir.toString()))
 1885   					fPathList.add(0, fExtractDir.toString());
 1886   				// filter only for the first SIX items
 1887   				if (fPathList.size() > fMaxExtractHistory)
 1888   					fPathList = new Vector(fPathList.subList(0, fMaxExtractHistory));
 1889   				
 1890   				boolean overwriteExisting = extract.isOverwriteExistingChecked();
 1891   				boolean skipOlder = extract.isSkipOlderChecked();
 1892   				boolean useFolder = extract.isUseFolderChecked();
 1893   				
 1894   				// validate destination directory
 1895   				if ((!destDir.isDirectory()) || (!destDir.exists())) {
 1896   					Utils.sayInformation(fResources.getString("key.message.dir_not_exists"),
 1897   										 Main.this);
 1898   					return;
 1899   				}
 1900   				
 1901   				// if user select files by filter - select on the table first
 1902   				if (extract.isFilteredFilesSelected()) {
 1903   					fTable.clearSelection();
 1904   					RE filter = Utils.getFileFilter(extract.getFileFilter());
 1905   					ArrayList filenames = fSupport.getAllFilenames();
 1906   					for (int i = 0; i < filenames.size(); i++) {
 1907   						String name = (String) filenames.get(i);
 1908   						if (filter.isMatch(name))
 1909   							fTable.addRowSelectionInterval(i, i);
 1910   					}
 1911   					fSupport.extract(	fTable.getSelectedRows(),
 1912   										destDir,
 1913   										overwriteExisting,
 1914   										skipOlder,
 1915   										useFolder);
 1916   				}
 1917   				
 1918   				// if user select all files option
 1919   				if (extract.isAllFilesSelected()) {
 1920   					int count = fTable.getRowCount();
 1921   					int[] indexes = new int[count];
 1922   					for (int i = 0; i < count; i++) {
 1923   						indexes[i] = i;
 1924   					}
 1925   					fSupport.extract(	indexes,
 1926   										destDir,
 1927   										overwriteExisting,
 1928   										skipOlder,
 1929   										useFolder);
 1930   				}
 1931   				
 1932   				// if extract user selection
 1933   				if (extract.isSelectedFilesSelected()) {
 1934   					if (fTableModel.isSelectedRow()) {
 1935   						fSupport.extract(	fTable.getSelectedRows(),
 1936   											destDir,
 1937   											overwriteExisting,
 1938   											skipOlder,
 1939   											useFolder);
 1940   					}
 1941   				}
 1942   			}
 1943   		}
 1944   		
 1945   	}// End of ExtractRunnable
 1946   	
 1947   	
 1948   	
 1949   	/**
 1950   	*	Open action executed in separate thread
 1951   	*/
 1952   	private final class OpenRunnable implements Runnable {
 1953   		
 1954   		OpenRunnable() {
 1955   		}
 1956   		
 1957   		public void run() {
 1958   			File file = null;
 1959   			JFileChooser chooser = new JFileChooser();
 1960   			chooser.setDialogTitle(fResources.getString("key.title.open_archive"));
 1961   			NeonFileFilter filter = new NeonFileFilter();
 1962   			filter.addExtension("zip");
 1963   			filter.setDescription("ZIP " + fResources.getString("key.title.archives"));
 1964   			chooser.setFileFilter(filter);
 1965   			int value = chooser.showOpenDialog(Main.this);
 1966   			
 1967   			if (value == JFileChooser.APPROVE_OPTION) {
 1968   				file = chooser.getSelectedFile();
 1969   				
 1970   				// if file does not exists
 1971   				if (!file.exists()) {
 1972   					Utils.sayWarning(fResources.getString("key.message.file_not_exists"), Main.this);
 1973   					return;
 1974   				}
 1975   				
 1976   				// clear old table content
 1977   				fTableData.clear();
 1978   				// clear previous selection
 1979   				ListSelectionModel tableSelection = fTable.getSelectionModel();
 1980   				tableSelection.setLeadSelectionIndex(0);
 1981   				tableSelection.clearSelection();
 1982   				
 1983   				Vector zipData = null;
 1984   				
 1985   				// invoke archive support interface
 1986   				try {
 1987   					zipData = fSupport.open(file);
 1988   				} catch (Exception e) {
 1989   					log.error("Error open file", e);
 1990   				}
 1991   				
 1992   				// test sorting code
 1993   				//Collections.sort(zipData);
 1994   				// end of test and sorting code
 1995   				
 1996   				fTableData.addAll(zipData);
 1997   				fTableModel.setDefaultSorting();
 1998   				fTable.updateUI();
 1999   				setTitle(TITLE + " - " + Utils.removePath(file.toString()));
 2000   				
 2001   			 	// add to FileMenu history
 2002   				fFileHistory.add(file.toString(), false);
 2003   				////
 2004   				
 2005   				Main.this.setDefaultRightStatusMessage();
 2006   			}
 2007   		}
 2008   		
 2009   	}
 2010   	
 2011   	
 2012   	
 2013   	/**
 2014   	*	Delete action executed in separate thread
 2015   	*/
 2016   	private final class DeleteRunnable implements Runnable {
 2017   		
 2018   		DeleteRunnable() {
 2019   		}
 2020   		
 2021   		public void run() {
 2022   			DeleteDialog dialog = new DeleteDialog(Main.this, true);
 2023   			dialog.setEntireArchiveSelected(!fTableModel.isSelectedRow());
 2024   			dialog.setSelectedFilesSelected(fTableModel.isSelectedRow());
 2025   			dialog.setSelectedFilesEnabled(fTableModel.isSelectedRow());
 2026   			dialog.show();
 2027   			
 2028   			if (dialog.isApproved()) {
 2029   				if (!fSupport.hasOpenFile()) return;
 2030   				// if user select files by filter - select on the table first
 2031   				if (dialog.isFilteredFilesSelected()) {
 2032   					fTable.clearSelection();
 2033   					RE filter = Utils.getFileFilter(dialog.getFileFilter());
 2034   					ArrayList filenames = fSupport.getAllFilenames();
 2035   					for (int i = 0; i < filenames.size(); i++) {
 2036   						String name = (String) filenames.get(i);
 2037   						if (filter.isMatch(name))
 2038   							fTable.addRowSelectionInterval(i, i);
 2039   					}
 2040   					fSupport.delete(fTable.getSelectedRows());
 2041   				}
 2042   				// if user select delete entire archive
 2043   				if (dialog.isEntireArchiveSelected()) {
 2044   					int count = fTable.getRowCount();
 2045   					int[] indexes = new int[count];
 2046   					for (int i = 0; i < count; i++) {
 2047   						indexes[i] = i;
 2048   					}
 2049   					fSupport.delete(indexes);
 2050   				}
 2051   				// if user select delete only selected files
 2052   				if (dialog.isSelectedFilesSelected()) {
 2053   					fSupport.delete(fTable.getSelectedRows());
 2054   				}
 2055   			}
 2056   		}
 2057   		
 2058   	}// End of DeleteRunnable
 2059   	
 2060   	
 2061   	
 2062   	/**
 2063   	*	Add action executed in separated thread
 2064   	*/
 2065   	private final class AddRunnable implements Runnable {
 2066   		
 2067   		AddRunnable() {
 2068   		}
 2069   		
 2070   		public void run() {
 2071   			AddDialog dialog = new AddDialog(Main.this, true);
 2072   			dialog.show();
 2073   			
 2074   			File current = fSupport.getCurrentOpen();
 2075   			if (current == null) return;
 2076   			Date date_before = new Date(current.lastModified());
 2077   			// if simple button is clicked
 2078   			if (dialog.isSimpleActionSelected()) {
 2079   				fSupport.add(	dialog.getSelectedFiles(),
 2080   								dialog.getCurrentDirectory(),
 2081   								fSupport.getCurrentOpen(),
 2082   								null,
 2083   								dialog.getAction(),
 2084   								dialog.getCompression(),
 2085   								dialog.isSubfoldersSelected(),
 2086   								dialog.isFullpathSelected());
 2087   				
 2088   			}
 2089   			
 2090   			// if add by regular expression button is clicked
 2091   			if (dialog.isFilterActionSelected()) {
 2092   				fSupport.add(	dialog.getSelectedFiles(),
 2093   								dialog.getCurrentDirectory(),
 2094   								fSupport.getCurrentOpen(),
 2095   								dialog.getFileFilter(),
 2096   								dialog.getAction(),
 2097   								dialog.getCompression(),
 2098   								dialog.isSubfoldersSelected(),
 2099   								dialog.isFullpathSelected());
 2100   			}
 2101   			Date date_after = new Date(current.lastModified());
 2102   			if (log.isDebugEnabled()) {
 2103   				log.debug("Date before modification: " + date_before.toString());
 2104   				log.debug("Date after modification: " + date_after.toString());
 2105   				log.debug("Dates equals?: " + date_after.equals(date_before));
 2106   			}
 2107   			if (!date_after.equals(date_before)) {
 2108   				refreshTable(current);
 2109   			}
 2110   		}
 2111   		
 2112   	} // End of AddRunnable
 2113   	
 2114   	
 2115   	
 2116   	/**
 2117   	*	Test of archive integrity running in separate thread.
 2118   	*/
 2119   	private final class TestIntegrityRunnable implements Runnable {
 2120   		
 2121   		TestIntegrityRunnable() {
 2122   		}
 2123   		
 2124   		public void run() {
 2125   			if (!fSupport.hasOpenFile()) return;
 2126   			boolean result = fSupport.test();
 2127   			if (result) {
 2128   				fOutputManager.insertFirst(fResources.getString("key.message.no_errors_detected_in_compressed_data"));
 2129   				//fOutputManager.insertFirst("" + '\n');
 2130   			} else {
 2131   				fOutputManager.insertFirst(fResources.getString("key.message.errors_where_detected_in_compressed_data"));
 2132   				//fOutputManager.insertFirst("" + '\n');
 2133   			}
 2134   			SwingUtilities.invokeLater(new Runnable() {
 2135   				public void run() {
 2136   					showLogDialog();
 2137   				}
 2138   			});
 2139   		}
 2140   	}
 2141   	
 2142   	
 2143   	
 2144   	/**
 2145   	*	Manager for Menu File last opens history.
 2146   	*/
 2147   	private final class FileHistoryManager {
 2148   		
 2149   		private final static int fMaxSize = 6;
 2150   		
 2151   		private Vector fHistoryList;
 2152   		
 2153   		FileHistoryManager() {
 2154   			fHistoryList = new Vector();
 2155   		}
 2156   		
 2157   		
 2158   		
 2159   		/**
 2160   		*	Maximum size of this history list.
 2161   		*/
 2162   		public int size() {
 2163   			return fMaxSize;
 2164   		}
 2165   		
 2166   		
 2167   		
 2168   		/**
 2169   		*	Append path to the beginning of the list.
 2170   		*	This method watch the list can't exceed maximum size
 2171   		*/
 2172   		public void add(String aPath, boolean aReverse) {
 2173   			if (!fHistoryList.contains(aPath)) {
 2174   				if (!aReverse)
 2175   					fHistoryList.add(0, aPath);
 2176   				else
 2177   					fHistoryList.add(fHistoryList.size(), aPath);
 2178   			} else { // if array already contains this item
 2179   				int index = fHistoryList.indexOf(aPath);
 2180   				fHistoryList.add(0, fHistoryList.remove(index));
 2181   			}
 2182   			if (fHistoryList.size() > fMaxSize)
 2183   				fHistoryList = new Vector(fHistoryList.subList(0, fMaxSize));
 2184   		}
 2185   		
 2186   		
 2187   		
 2188   		/**
 2189   		*	Get path string at the specified index.
 2190   		*/
 2191   		public String get(int aIndex) {
 2192   			return (String) fHistoryList.get(aIndex);
 2193   		}
 2194   		
 2195   		
 2196   		
 2197   		/**
 2198   		*	Draw this history list to FileMenu.
 2199   		*/
 2200   		public void drawToMenu() {
 2201   			fMenuRecent.removeAll();
 2202   			int size = fFileHistory.size();
 2203   			for (int i = 0; i < size; i++) {
 2204   				String file = null;
 2205   				try {
 2206   					file = fFileHistory.get(i);
 2207   				} catch(ArrayIndexOutOfBoundsException e) {
 2208   					break;
 2209   				}
 2210   				//fMenuRecent.insert(fFileHistory.get(i), 0);
 2211   				JMenuItem item = new JMenuItem(new RecentFilesAction());
 2212   				item.setText(fFileHistory.get(i));
 2213   				fMenuRecent.add(item);
 2214   			}
 2215   		}
 2216   		
 2217   	}
 2218   	
 2219   	
 2220   	
 2221   	/**
 2222   	*	Component that disable all input events.
 2223   	*/
 2224   	private class GlassComponent extends JComponent implements
 2225   		AWTEventListener {
 2226   	
 2227   		Window parentWindow;
 2228   	
 2229   		public GlassComponent() {
 2230   			super();
 2231   			this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 2232   			setOpaque(false);
 2233   			
 2234   			addMouseListener(new MouseAdapter() {});
 2235   		}
 2236   	
 2237   		/**
 2238   		* Override setVisible to install/remove key events hook
 2239   		that will allow us to
 2240   		* disable key events when the glass pane is visible.
 2241   		*/
 2242   		public void setVisible(boolean visible) {
 2243   			if (visible) {
 2244   			if (this.parentWindow == null)
 2245   			this.parentWindow =
 2246   			SwingUtilities.windowForComponent(this);
 2247   			
 2248   			Toolkit.getDefaultToolkit().addAWTEventListener
 2249   			(this, AWTEvent.KEY_EVENT_MASK);
 2250   			}
 2251   			else {
 2252   			Toolkit.getDefaultToolkit().removeAWTEventListener
 2253   			(this);
 2254   			}
 2255   			super.setVisible(visible);
 2256   		}
 2257   		
 2258   		/**
 2259   		* Called whenever ther is an event in AWT queue. Note that
 2260   		the current implementation
 2261   		* skips all key events, not just events for this window.
 2262   		Logic can be enhanced to examine
 2263   		* the source of the event and it's parent window and skip
 2264   		only those events
 2265   		* that originated from disabled window
 2266   		*/
 2267   		public void eventDispatched(AWTEvent event) {
 2268   			if (event instanceof KeyEvent && event.getSource()
 2269   			instanceof Component) {
 2270   				if (SwingUtilities.windowForComponent((Component)
 2271   				event.getSource()) == this.parentWindow)
 2272   				// Consume events only for our window
 2273   				((KeyEvent)event).consume();
 2274   				}
 2275   			}
 2276   	}
 2277   	
 2278   	
 2279   	
 2280   }

Save This Page
Home » openjdk-7 » net.sourceforge » neonzip » [javadoc | source]