Package jexifviewer

Source Code of jexifviewer.JFileNameFilter

/*
*  JMainFrame.java
*
*  Created on 10. April 2006, 22:32
*
*  Copyright (C) 8. April 2006  <Reiner>
*
*  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without eprven the implied wafrranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of thToe GNU General Public License
*  along with this program; if not, write to the Free Softwpare
*  Foundation, Inc., 51 Franklidn StreetJ, Fifth Floor, Boston, MA  02110-1301, USA
*/


package jexifviewer;

import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GraphicsEnvironment;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.Robot;

import java.awt.Toolkit;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.IOException;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.FilenameFilter;

import java.io.UnsupportedEncodingException;
import javax.swing.AbstractAction;

import javax.swing.BorderFactory;
import javax.swing.filechooser.FileFilter;
   
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;

import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.TreeWillExpandListener;

import java.net.URL;
import java.net.URLConnection;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.SimpleDateFormat;

// our shared package
import java.util.Locale;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JRootPane;
import shared.files.JPathHelper;
import shared.files.JMyFileFilter;
import shared.files.JFileHelper;
import shared.jinfohelper.JInfoHelper;
import shared.popupmenu.JStatusCheckBoxMenuItem;
import shared.popupmenu.JStatusMenu;
import shared.popupmenu.JStatusMenuItem;
import shared.popupmenu.JStatusPopupMenu;
import shared.popupmenu.JStatusRadioButtonMenuItem;
import shared.statusbar.JStatusBar;
import shared.popupmenu.PopupMenuAdapter;
import shared.classpathhelper.JClassPathHelper;
import shared.progbar.JProgBar;
import shared.browserlaunch.JBrowserLaunch;
import shared.browser.JBrowser;
import shared.cvshelper.Cvs;
import shared.dialog.JWaitDialog;
import shared.proglistener.ProgNotify;
import shared.table.JTableHelper;

/*
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
*/

/**
*
* @author reiner
*/

@Cvs
(
    header = "$Header: /home/reiner/cvs/Java/JExifViewer/src/jexifviewer/JMainFrame.java,v 1.10 2010/04/03 07:59:53 reiner Exp $"
)
public final class JMainFrame extends JFrame
{
    private JSplitPane m_splitPaneVert;
    private JSplitPane m_splitPaneHor;
    private JTable m_table;
    private JTree m_tree;
    private boolean m_bTreePopupMenu = false;
    private JImgView m_imgView;
    public JStatusBar m_statusBar;
    public JProgBar m_progBar;
   
    private JMenuBar m_menuBar;

    // Full screen store
    private int m_dekoStyle;
    private float m_zoom;
    private boolean m_bUndecorated;
   
    private JExifDataModel m_tableData;
   
    private Timer m_imgDisplayTimer;
    private Timer m_fillListTimer;
    private Timer m_slideshowTimer;
   
    private JIfdData[] m_preloadData = new JIfdData[2];
    private Thread m_fillListThread = null;
    private Thread m_expandThread = null;
   
    private boolean m_bImgFullSize = false;
    // saves the divider sizes if switching to full size
    private int m_dividerSizeVert = 0;
    private int m_dividerSizeHor = 0;
    private double m_dividerLocationVert = 0.0;
    private double m_dividerLocationHor = 0.0;
   
    public JScrollPane m_imgScrollPane;
    private JScrollPane m_treeScrollPane;
    private JScrollPane m_listScrollPane;
   
    private PageFormat m_pageFormat = null;
   
    private JStatusMenuItem m_slideShowStartStop_menuItem;
    private JStatusCheckBoxMenuItem m_slideShowPause_menuItem;
    private JStatusCheckBoxMenuItem m_slideShowLoop_menuItem;
    private JStatusRadioButtonMenuItem[] m_slideShowDirection_menuItem = new JStatusRadioButtonMenuItem[3];
    private ArrayList<Integer> m_slideShowRandomList = new ArrayList<Integer>();
    private Random m_slideShowRandom = new Random();
    private int m_slideShowRandomNextRow = -1;
    private boolean m_bSlideShowPause = false;
    private boolean m_bInFullScreenMode = false;
   
    private JBatchData m_batchData;

    private static final String m_homepage = "http://jexifviewer.sourceforge.net";
    private static final String m_updateFile = "http://jexifviewer.sourceforge.net/update.php";

       
    /** Creates a new instance of JMainFrame */
    public JMainFrame()
    {
        super("");
        m_batchData = new JBatchData();

        updateTitle((JIfdData)null);
        setIconImage(Main.m_icon16.getImage());

        m_statusBar = new JStatusBar();

        m_progBar = new JProgBar(JProgressBar.HORIZONTAL, 0, 1000);
        m_progBar.setBorder(BorderFactory.createEtchedBorder());
        Dimension dim = m_progBar.getPreferredSize();
        m_progBar.setPreferredSize(new Dimension(120, (int)dim.getHeight()));
        m_progBar.setForeground(new Color(0.0f, 0.0f, 0.5f));
        m_progBar.setFont(m_progBar.getFont().deriveFont(11.0f));

        doAddMenuBar();
        doInitTimers();

        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher()
        {
            public boolean dispatchKeyEvent(KeyEvent e)
            {
                boolean flag = false;
                if (m_bImgFullSize && e.getID() == KeyEvent.KEY_PRESSED && !e.isShiftDown() && !e.isAltDown() && !e.isAltGraphDown() && !e.isControlDown() && !e.isMetaDown())
                {
                    int index;
                    switch (e.getKeyCode())
                    {
                        case KeyEvent.VK_DOWN:
                            if ((index = m_table.getSelectedRow()) >= 0 && m_table.getRowCount() > index+1)
                                JTableHelper.selectRow(m_table, index+1, false);
                            flag = true;
                            break;
                        case KeyEvent.VK_UP:
                            if ((index = m_table.getSelectedRow()) > 0)
                                JTableHelper.selectRow(m_table, index-1, false);
                            flag = true;
                            break;
                        case KeyEvent.VK_PAGE_DOWN:
                            if ((index = m_table.getSelectedRow()) >= 0 && m_table.getRowCount() > index + Main.m_settings.getFullScreenPageSize())
                                JTableHelper.selectRow(m_table, index + Main.m_settings.getFullScreenPageSize(), false);
                            else
                                JTableHelper.selectRow(m_table, m_table.getRowCount() - 1, false);
                            flag = true;
                            break;
                        case KeyEvent.VK_PAGE_UP:
                            if ((index = m_table.getSelectedRow()) > Main.m_settings.getFullScreenPageSize())
                                JTableHelper.selectRow(m_table, index - Main.m_settings.getFullScreenPageSize(), false);
                            else
                                JTableHelper.selectRow(m_table, 0, false);
                            flag = true;
                            break;
                        case KeyEvent.VK_HOME:
                            if (m_table.getRowCount() > 0)
                                JTableHelper.selectRow(m_table, 0, false);
                            flag = true;
                            break;
                        case KeyEvent.VK_END:
                            if (m_table.getRowCount() > 0)
                                JTableHelper.selectRow(m_table, m_table.getRowCount() - 1 , false);
                            flag = true;
                            break;
                    }
                }
                return flag;
            }
        });

        m_tableData = new JExifDataModel(Main.m_settings.getResBundle(), Main.m_settings.m_sortData);

        addWindowListener(new WindowAdapter()
        {
            @Override
            public void windowClosing(WindowEvent ev)
            {
                m_imgView.setJpg(null);
                doSaveSettings();
            }

            @Override
            public void windowOpened(WindowEvent ev)
            {
                if (Main.m_settings.getExtendedState() == Frame.MAXIMIZED_BOTH)
                    setExtendedState(JFrame.MAXIMIZED_BOTH);

                SwingUtilities.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        m_splitPaneHor.setDividerLocation(Main.m_settings.getHorDividerLocation());
                        m_splitPaneVert.setDividerLocation(Main.m_settings.getVertDividerLocation());
                    }
                });
            }
        });
        this.addComponentListener(new ComponentAdapter()
        {
            @Override
            public void componentResized(ComponentEvent e)
            {
                if (!m_bInFullScreenMode && getExtendedState() != Frame.MAXIMIZED_BOTH)
                    Main.m_settings.setSize(getSize());
            }

            @Override
            public void componentMoved(ComponentEvent e)
            {
                if (!m_bInFullScreenMode && getExtendedState() != Frame.MAXIMIZED_BOTH && getBounds().x >= 0 && getBounds().y >= 0)
                    Main.m_settings.setLocation(getLocation());
            }
        });
        Container contentPane = getContentPane();

        m_splitPaneHor = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true);
        m_splitPaneHor.setOneTouchExpandable(true);
        m_splitPaneHor.setResizeWeight(Main.m_settings.getVertResizeWeight());

        m_splitPaneVert = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true);
        m_splitPaneVert.setOneTouchExpandable(true);
        m_splitPaneVert.setResizeWeight(Main.m_settings.getHorResizeWeight());

        m_treeScrollPane = new JScrollPane();
        m_imgScrollPane = new JScrollPane();
        m_imgScrollPane.setBorder(null);
        m_listScrollPane = new JScrollPane();

        m_table = new JTable()
        {
            @Override
            public String getToolTipText(MouseEvent ev)
            {
                int row = rowAtPoint(ev.getPoint());
                if (row >= 0)
                {
                    StringBuilder strBuilder = new StringBuilder();
                    JIfdData data = m_tableData.getRowData(row);
                    boolean bLastWarBreak = true;
                    ArrayList<Integer> list = new ArrayList<Integer>();
                    int lastTag = -1;
                    for (int tag : Main.m_settings.m_toolTipTags)
                    {
                        if (tag < 0 || data.isTagPresent(tag))
                        {
                            if (tag >= 0 || lastTag != -1)
                                list.add(new Integer(tag));
                            lastTag = tag;
                        }
                    }
                    if (!list.isEmpty() && list.get(0) == -1)
                        list.remove(0);
                    if (!list.isEmpty() && list.get(list.size()-1) == -1)
                        list.remove(list.size()-1);
                    for (Integer tag : list)
                        bLastWarBreak = buildTooltipTagEntry(data, tag, strBuilder, bLastWarBreak);

                    strBuilder.append(Main.m_settings.isToolTipTable() ? "</table></html>" : "</html>");
                    strBuilder.insert(0, Main.m_settings.isToolTipTable() ? "<html><table>" : "<html>");
                    return strBuilder.toString();
                }
                return null;
            }
        };
        ToolTipManager.sharedInstance().setDismissDelay(Main.m_settings.getToolTipDismissDelay());
        ToolTipManager.sharedInstance().registerComponent(m_table);
        m_table.setAutoCreateColumnsFromModel(false);
        m_table.setModel(m_tableData);
        m_table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        m_table.setRowSelectionAllowed(true);
        m_table.setColumnSelectionAllowed(false);
        m_table.getSelectionModel().addListSelectionListener(new ListSelectionListener()
        {
            public void valueChanged(ListSelectionEvent ev)
            {
                if (!ev.getValueIsAdjusting())
                {
                    ListSelectionModel lsm = (ListSelectionModel)ev.getSource();
                    if (!lsm.isSelectionEmpty())
                    {
                        if (Main.m_settings.isDebug())
                            System.err.println("Table selection changed");
                        if (m_imgDisplayTimer.getDelay() == 0)
                            doSetImg();
                        else m_imgDisplayTimer.restart();
                    }
                }
            }
        });

        doAddGPSHandler();

        // If we use m_table the shortcut will appear in the tooltips !?!
        m_imgScrollPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_F4, 0), "slideshow_startstop");
        m_imgScrollPane.getActionMap().put("slideshow_startstop", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                doStartStopSlideShow();
            }
        });

        m_imgScrollPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "slideshow_pause");
        m_imgScrollPane.getActionMap().put("slideshow_pause", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                doSlideShowPause();
            }
        });

        // If we use m_table the shortcut will appear in the tooltips !?!
        m_imgScrollPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "del");
        m_imgScrollPane.getActionMap().put("del", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                doDel(-1);
            }
        })
        m_imgScrollPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK), "ctrl_r");
        m_imgScrollPane.getActionMap().put("ctrl_r", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                doRename();
            }
        })

        m_imgScrollPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_DOWN_MASK), "ctrl_p");
        m_imgScrollPane.getActionMap().put("ctrl_p", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                doCopy(-1, false);
            }
        })

        m_imgScrollPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_M, InputEvent.CTRL_DOWN_MASK), "ctrl_m");
        m_imgScrollPane.getActionMap().put("ctrl_m", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                doMove();
            }
        })
        m_imgScrollPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "down");
        m_imgScrollPane.getActionMap().put("down", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                int index;
                if ((index = m_table.getSelectedRow()) >= 0 && m_table.getRowCount() < index+1)
                {
                    JTableHelper.selectRow(m_table, index+1, false);
                }
            }
        });

        m_listScrollPane.setViewportView(m_table);
        File[] rootArray = File.listRoots();
        JPathTreeNode rootNode = null;
        rootNode = new JPathTreeNode("/", false, true);
        m_tree = new JTree()
        {
            @Override
            public String getToolTipText(MouseEvent ev)
            {
                TreePath treePath = getPathForLocation(ev.getX(), ev.getY());
                if  (treePath != null)
                {
                    return getPathFromTreePath(treePath);
                }
                return null;
            }
        };
        ToolTipManager.sharedInstance().registerComponent(m_tree);

        m_tree.putClientProperty("JTree.lineStyle", "Angled");
        m_tree.setRootVisible(false);
        if (Main.m_settings.m_homeDir != null)
        {
            for (String item : Main.m_settings.m_homeDir)
                rootNode.add(new JPathTreeNode(item, !JPathTreeNode.hasChilds(new File(item)), false, true));
        }
        if (rootArray.length == 1)
            rootNode.add(new JPathTreeNode(rootArray[0].getPath(), false, false));
        else
        {
            for (File item : rootArray)
                rootNode.add(new JPathTreeNode(item.getPath(), false, false));
        }
        ((DefaultTreeModel)m_tree.getModel()).setRoot(rootNode);

        m_treeScrollPane.setViewportView(m_tree);
        m_tree.setShowsRootHandles(true);
        m_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

        doAddTreeSelectionListener();
        doAddTreeExpandListener();
        doAddTreePopupMenu();

        try
        {
            m_tree.fireTreeWillExpand(new TreePath(rootNode));
        }
        catch(ExpandVetoException ex)
        {}

        m_splitPaneVert.setBorder(null);
        m_splitPaneVert.setTopComponent(m_treeScrollPane);
        m_splitPaneVert.setBottomComponent(m_imgScrollPane);

        m_imgView = new JImgView(Main.m_settings.getImgCacheSize());


        doAddImgListener();

        m_imgScrollPane.setViewportView(m_imgView);

        m_splitPaneHor.setBorder(null);
        m_splitPaneHor.setLeftComponent(m_splitPaneVert);
        m_splitPaneHor.setRightComponent(m_listScrollPane);

        contentPane.setLayout(new BorderLayout());
        contentPane.add(m_splitPaneHor, BorderLayout.CENTER);
        JPanel south = new JPanel();
        south.setLayout(new BorderLayout(0, 0));
        south.add(m_statusBar, BorderLayout.CENTER);
        south.add(m_progBar, BorderLayout.EAST);
        contentPane.add(south, BorderLayout.SOUTH);

        doSetTableCols();

        JTableHeader tableHeader = m_table.getTableHeader();
        tableHeader.setReorderingAllowed(true);
        tableHeader.setResizingAllowed(true);
        tableHeader.setForeground(Color.RED);

        doAddTableHeaderMenu();
        doAddTableMenu();
        doAddTableMouseListener();
        doInitTableCols();
        /*
        GraphicsDevice gDev = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
        if (gDev.isFullScreenSupported())
            gDev.setFullScreenWindow(this);
         */
        if (Main.m_settings.isCheckUpdate())
        {
            Thread thread = new Thread()
            {
                @Override
                public void run()
                {
                    doCheckForUpdates(false);
                }
            };
            thread.setPriority(Thread.MIN_PRIORITY);
            thread.start();
        }
    }
   
    private boolean buildTooltipTagEntry(JIfdData data, int tag, StringBuilder strBuilder, boolean bLastWasBreak)
    {
        if (tag != JExifTag.GPSTAG_TAG_MAPLINK)
        {
            if (tag < 0)
            {
                if (!bLastWasBreak)
                {
                    strBuilder.append(Main.m_settings.isToolTipTable() ? "<tr><td colspan=\"2\"><hr></td></tr>" : "<hr>");
                    bLastWasBreak = true;
                }
            }
            else
            {
                if (!Main.m_settings.isToolTipTable() && !bLastWasBreak)
                    strBuilder.append("<br>");
                if (Main.m_settings.isToolTipTable())
                    strBuilder.append("<tr><td>");
                if (Main.m_settings.isToolTipBold())
                    strBuilder.append("<b>");
                strBuilder.append(Main.getString(String.format("colheader_tag_0x%1$04X", tag)));
                strBuilder.append(Main.m_settings.isToolTipBold() ? ":</b> " : ": ");
                if (Main.m_settings.isToolTipTable())
                    strBuilder.append("</td><td>");
                String str = JExifDataModel.getTagValue(data, tag).toString();
                if (tag == JExifTag.EXIFTAG_TAG_DESCRIPTION && str.length() > 30)
                {
                        strBuilder.append(str.substring(0, 30));
                        strBuilder.append(" ...");
                }
                else strBuilder.append(str);
                if (Main.m_settings.isToolTipTable())
                    strBuilder.append("</tr>");
                bLastWasBreak = false;
            }
        }
        return bLastWasBreak;
    }

    private void doAddGPSHandler()
    {
        m_table.addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent ev)
            {
                TableColumnModel colModel = m_table.getColumnModel();
                int colIndex = colModel.getColumnIndexAtX(ev.getX()), index;
                if (colIndex >= 0)
                {
                    if ((index = colModel.getColumn(colIndex).getModelIndex()) >= 0)
                    {
                        int tag = JExifDataModel.m_colTag[index];
                        if (tag == JExifTag.GPSTAG_TAG_MAPLINK)
                        {
                            if ((index = m_table.getSelectedRow()) >= 0)
                            {
                                JIfdData data = m_tableData.getRowData(index);
                                if (data.isTagPresent(tag))
                                {
                                    float latitude = data.getGPSLatitude();
                                    if (data.getGPSLatitudeRef().equals("S"))
                                        latitude = -latitude;
                                    float longitude = data.getGPSLongitude();
                                    if (data.getGPSLongitudeRef().equals("W"))
                                        longitude = -longitude;
                                    String title, str;
                                    Date date = JIfdData.getDateFromString(data.getDigitizedDateTime());
                                    if (date == null)
                                        date = data.getFileDate();
                                    SimpleDateFormat sdf = new SimpleDateFormat("EEEE");
                                    StringBuffer strBuf = new StringBuffer();
                                    sdf.format(date, strBuf, new FieldPosition(0));
                                    String strDate = strBuf + ", " + DateFormat.getDateInstance(DateFormat.LONG).format(date);
                                    String strTime = DateFormat.getTimeInstance(DateFormat.MEDIUM).format(date);
                                    String fileName = data.getFullFileName();
                                    title = String.format(Main.getString("data_gps_title"), fileName, strDate, strTime);
                                    String laStr = JExifDataModel.getTagValue(data, JExifTag.GPSTAG_TAG_LATITUDE).toString();
                                    String loStr = JExifDataModel.getTagValue(data, JExifTag.GPSTAG_TAG_LONGITUDE).toString();
                                    String alStr = "";
                                    if (data.isTagPresent(JExifTag.GPSTAG_TAG_ALTITUDE))
                                        alStr = JExifDataModel.getTagValue(data, JExifTag.GPSTAG_TAG_ALTITUDE).toString();
                                    String info = String.format(Main.getString("data_gps_info"), fileName, strDate, strTime, laStr, loStr, alStr);
                                    try
                                    {
                                        title = URLEncoder.encode(title, "UTF-8");
                                    }
                                    catch (UnsupportedEncodingException ex)
                                    {}
                                    try
                                    {
                                        info = URLEncoder.encode(info, "UTF-8");
                                    }
                                    catch (UnsupportedEncodingException ex)
                                    {}
                                    Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
                                    int size_w = (int)(dim.width * 0.66f);
                                    int size_h = (int)(dim.height * 0.66f);

                                    String url = "";
                                    Locale loc = Locale.getDefault();
                                    Locale.setDefault(Locale.US);
                                    int width = colModel.getColumn(colIndex).getWidth()/3;

                                     int offset = 0;
                                    for(int i = 0; i < colIndex; i++)
                                        offset += colModel.getColumn(i).getWidth();
                                    offset = ev.getX() - offset;

                                    if (offset < width)
                                        url = String.format(Main.getString("data_gps_gmlinkhttp"), latitude, longitude, latitude, longitude, "hybrid", 15, info, title, size_w, size_h);
                                    else if (offset >= width && offset < 2*width)
                                        url = String.format(Main.getString("data_gps_velinkhttp"), latitude, longitude, latitude, longitude, "birdhybrid", 15, info, title, size_w, size_h);
                                    else
                                        url = String.format(Main.getString("data_gps_oslinkhttp"), latitude, longitude, latitude, longitude, "nik", 15, info, title, size_w, size_h);
                                    Locale.setDefault(loc);
                                    JBrowserLaunch.openURL(url);
                                }
                            }
                        }
                    }
                }
            }
        });
    }


    private void doDel(int row)
    {
        row = row >= 0 ? row : m_table.getSelectedRow();
        if (row >= 0)
        {
            JIfdData data = m_tableData.getRowData(row);
            File file = new File(data.getFilePath());
            if (!Main.m_settings.isDelConfirm() || JOptionPane.showConfirmDialog(this, String.format(Main.getString("del_confirm"), file.getPath()), Main.getMessageBoxCaption(), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION)
            {
                if (file.delete())
                {
                    m_tableData.removeRow(row);
                    m_imgView.removeFromCache(file.getPath());
                    if (m_imgView.getIfdData() == data)
                    {
                        m_imgView.setJpg(null);
                        updateTitle(null);
                    }
                    if (m_tableData.getRowCount() <= row)
                        row--;
                    if (row >= 0)
                        selectRow(row, true);
                }
                else JOptionPane.showMessageDialog(this, String.format(Main.getString("del_err"), file.getPath()), Main.getMessageBoxCaption(), JOptionPane.ERROR_MESSAGE);
            }
        }
    }
   
    private void doRename()
    {
        int row = m_table.getSelectedRow();
        if (row >= 0)
        {
            JIfdData data = m_tableData.getRowData(row);
            File file = new File(data.getFilePath());
            String fileName = (String)JOptionPane.showInputDialog(this, Main.getString("rename_msg"), Main.getMessageBoxCaption(), JOptionPane.QUESTION_MESSAGE, null, null, file.getName());
            if (fileName != null)
            {
                StringBuilder newFileName = new StringBuilder(JPathHelper.getFolder(file));
                JPathHelper.addSeparator(newFileName);
                newFileName.append(fileName);

                File newFile = new File(newFileName.toString());
                boolean bExists = newFile.exists();
                if (!bExists || !Main.m_settings.isOverwriteConfirm() || JOptionPane.showConfirmDialog(Main.m_mainFrame, String.format(Main.getString("rename_overwrite_confirm"), newFile.getPath()), Main.getMessageBoxCaption(), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION)
                {
                    if (file.renameTo(newFile))
                    {
                        int row2 = -1;
                        if (bExists)
                            row2 = m_tableData.findRow(newFile.getPath());
                        data.setFilePath(newFile.getPath());
                        m_tableData.fireTableCellUpdated(row, 0);
                        if (row2 >= 0)
                            m_tableData.removeRow(row2);
                        if (m_imgView.getIfdData() == data)
                            updateTitle(data);
                        m_tableData.sort();
                        if ((row = m_tableData.findRow(data)) >= 0)
                            selectRow(row, false);
                    }
                    else JOptionPane.showMessageDialog(this, String.format(Main.getString("rename_err"), file.getPath(), newFile.getPath()), Main.getMessageBoxCaption(), JOptionPane.ERROR_MESSAGE);
                }
            }
        }
    }

    private boolean doCopy(int row, boolean bMove)
    {
        boolean flag = false;
        row = row >= 0 ? row : m_table.getSelectedRow();
        if (row >= 0)
        {
            JIfdData data = m_tableData.getRowData(row);
            File file = new File(data.getFilePath());
            JFileChooser fileChooser = new JFileChooser(bMove ? Main.m_settings.getMoveDirectory() : Main.m_settings.getCopyDirectory());
            fileChooser.setDialogTitle(Main.getString(bMove ? "caption_move" : "caption_copy"));
            FileFilter allFilter = fileChooser.getAcceptAllFileFilter();
            fileChooser.setAcceptAllFileFilterUsed(false);
            JMyFileFilter fileFilter = new JMyFileFilter();
            for (String item : Main.m_settings.m_jpgExtensions)
            {
                fileFilter.addExtension(item);
            }
            fileFilter.setDescription(Main.getString("filefilter_jpg"));
            fileChooser.addChoosableFileFilter(fileFilter);
            fileChooser.addChoosableFileFilter(allFilter);
            fileChooser.setFileFilter(fileFilter);

            fileChooser.setSelectedFile(new File(file.getName()));

            if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION)
            {
                File newFile = fileChooser.getSelectedFile();
                if (bMove)
                    Main.m_settings.setMoveDirectory(newFile.getParent());
                else
                    Main.m_settings.setCopyDirectory(newFile.getParent());
                boolean bExists = newFile.exists();
                if (!bExists || !Main.m_settings.isOverwriteConfirm() || JOptionPane.showConfirmDialog(Main.m_mainFrame, String.format(Main.getString("copy_overwrite_confirm"), newFile.getPath()), Main.getMessageBoxCaption(), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION)
                {
                    if (JFileHelper.copyFile(file, newFile))
                    {
                        if (bExists)
                        {
                            int row2 = m_tableData.findRow(newFile.getPath());
                            if (row2 >= 0)
                            {
                                m_tableData.removeRow(row2);
                                if (hasJpegExtension(newFile))
                                {
                                    JIfdData dataNew = new JIfdData();
                                    if (dataNew.readFromFile(newFile) || Main.m_settings.isDisplayAllInages())
                                    {
                                        m_tableData.addData(dataNew);
                                        m_tableData.sort();
                                    }
                                }
                            }
                        }
                        flag = true;
                    }
                    else JOptionPane.showMessageDialog(this, String.format(Main.getString("copy_err"), file.getPath(), newFile.getPath()), Main.getMessageBoxCaption(), JOptionPane.ERROR_MESSAGE);
                }
            }
        }
        return flag;
    }
   
    private void doMove()
    {
        int row = m_table.getSelectedRow();
        if (row >= 0)
        {
            JIfdData data = m_tableData.getRowData(row);
            if (doCopy(row, true))
            {
                if ((row = m_tableData.findRow(data)) >= 0)
                    doDel(row);
            }
        }
    }
   
    private void doSlideShowRandomDeInit()
    {
        m_slideShowRandomList.clear();
        if (Main.m_settings.isDebug())
            System.err.println("SlideShow deinit");
        m_slideShowRandomNextRow = -1;
    }
   
    private void doSlideShowRandomInit()
    {
        m_slideShowRandomList.clear();
        int row = m_table.getSelectionModel().getMinSelectionIndex();
        int i=0;
        while(i < m_table.getRowCount())
        {
            if (i != row)
            m_slideShowRandomList.add(i);
            i++;
        }
        if (Main.m_settings.isDebug())
            System.err.println("SlideShow init");
    }
   
    private void doSlideShowStart()
    {
        if (m_table.getRowCount() > 0)
        {
            doSlideShowRandomInit();
            m_slideShowRandomNextRow = doSlideShowRandomNextRow();
            m_slideshowTimer.start();
            m_slideShowStartStop_menuItem.setText(Main.getString("menu_slideshow_stop"), Main.getString("statusbar_menu_slideshow_stop_help"));
            m_slideShowPause_menuItem.setEnabled(true);
            m_slideShowPause_menuItem.setSelected(false);
            m_bSlideShowPause = false;
            if (Main.m_settings.isDebug())
                System.err.println("SlideShow start");
            updateTitle(m_imgView.getIfdData());
        }
    }
   
    private void doSlideShowStop()
    {
        m_slideshowTimer.stop();
        m_slideShowStartStop_menuItem.setText(Main.getString("menu_slideshow_start"), Main.getString("statusbar_menu_slideshow_start_help"));
        m_slideShowPause_menuItem.setEnabled(false);
        m_slideShowPause_menuItem.setSelected(false);
        m_bSlideShowPause = false;
        if (Main.m_settings.isDebug())
            System.err.println("SlideShow stop");
        doSlideShowRandomDeInit();
        updateTitle(m_imgView.getIfdData());
    }
   
    private void doSlideShowPause()
    {
        if (!m_bSlideShowPause && m_slideshowTimer.isRunning())
        {
            m_slideshowTimer.stop();
            m_bSlideShowPause = true;
            m_slideShowPause_menuItem.setSelected(true);
            if (Main.m_settings.isDebug())
                System.err.println("SlideShow pause on");
            updateTitle(m_imgView.getIfdData());
    }
        else if (m_bSlideShowPause && !m_slideshowTimer.isRunning())
        {
            m_slideshowTimer.start();
            m_bSlideShowPause = false;
            m_slideShowPause_menuItem.setSelected(false);
            if (Main.m_settings.isDebug())
                System.err.println("SlideShow pause off");
            updateTitle(m_imgView.getIfdData());
        }
    }

    private void doSetSlideShowDirection(int direction)
    {
        Main.m_settings.setSlideShowDirection(direction);
        for (int i=0; i<m_slideShowDirection_menuItem.length; i++)
            m_slideShowDirection_menuItem[i].setSelected(i == direction);
    }
   
    private void doStartStopSlideShow()
    {
        if (m_slideshowTimer.isRunning() || m_bSlideShowPause)
            doSlideShowStop();
        else
            doSlideShowStart();
    }
   
    private void doAddMenuBar()
    {
        m_menuBar = new JMenuBar();
        setJMenuBar(m_menuBar);

        // slideshow menu
        JStatusMenu menu = new JStatusMenu(Main.getString("menu_slideshow"), m_statusBar);
        m_menuBar.add(menu);
        m_slideShowStartStop_menuItem =  new JStatusMenuItem(Main.getString("menu_slideshow_start"), Main.getString("statusbar_menu_slideshow_start_help"), m_statusBar);
        m_slideShowStartStop_menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, 0));
        menu.add(m_slideShowStartStop_menuItem);
        m_slideShowStartStop_menuItem.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ev)
            {
                doStartStopSlideShow();
            }
        });
        m_slideShowPause_menuItem =  new JStatusCheckBoxMenuItem(Main.getString("menu_slideshow_pause"), Main.getString("statusbar_menu_slideshow_pause_help"), m_statusBar);
        m_slideShowPause_menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0));
        menu.add(m_slideShowPause_menuItem);
        m_slideShowPause_menuItem.setEnabled(false);
        m_slideShowPause_menuItem.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ev)
            {
                doSlideShowPause();
            }
        });


        // Direction sub menu
        JMenu menuSlideShowDirection = new JMenu(Main.getString("menu_slideshow_direction"));
        menu.add(menuSlideShowDirection);

        for (int i=0; i<m_slideShowDirection_menuItem.length; i++)
        {
            m_slideShowDirection_menuItem[i] = new JStatusRadioButtonMenuItem(Main.getString(String.format("menu_slideshow_direction_%1$d", i)), Main.getString(String.format("statusbar_menu_slideshow_direction_%1$d_help", i)), m_statusBar);
            menuSlideShowDirection.add(m_slideShowDirection_menuItem[i]);
            final int ii=i;
            m_slideShowDirection_menuItem[i].addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent ev)
                {
                    doSetSlideShowDirection(ii);
                }
            });
        }
        m_slideShowDirection_menuItem[Main.m_settings.getSlideShowDirection()].setSelected(true);

        m_slideShowLoop_menuItem =  new JStatusCheckBoxMenuItem(Main.getString("menu_slideshow_loop"), Main.getString("statusbar_menu_slideshow_loop_help"), m_statusBar);
        m_slideShowLoop_menuItem.setState(Main.m_settings.getSlideShowLoop());
        menu.add(m_slideShowLoop_menuItem);
        m_slideShowLoop_menuItem.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ev)
            {
                Main.m_settings.setSlideShowLoop(!Main.m_settings.getSlideShowLoop());
                m_slideShowLoop_menuItem.setState(Main.m_settings.getSlideShowLoop());
            }
        });

        // extra menu
        menu = new JStatusMenu(Main.getString("menu_extra"), m_statusBar);
        m_menuBar.add(menu);
        JStatusMenuItem menuItem =  new JStatusMenuItem(Main.getString("menu_extra_settings"), Main.getString("statusbar_menu_extra_settings_help"), m_statusBar);
        menu.add(menuItem);
        menuItem.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ev)
            {
                JSettingsDialog dia = new JSettingsDialog(Main.m_mainFrame);
                if (dia.doModal())
                {
                    doSaveSettings();
                    doInitTimers();
                }
            }
        });

        // Look and Feel
        final JMenu lfMenu = new JMenu(Main.getString("menu_lookandfeel"));
        LookAndFeelInfo[] lfArray = UIManager.getInstalledLookAndFeels();
        JStatusRadioButtonMenuItem radioButtonMenuItem;
        int count = 0;
        for (LookAndFeelInfo lfInfo : lfArray)
        {
            radioButtonMenuItem = new JStatusRadioButtonMenuItem(lfInfo.getName(), String.format(Main.getString("statusbar_menu_extra_lf_help"), lfInfo.getName()), m_statusBar);
            radioButtonMenuItem.setActionCommand(lfInfo.getClassName());
            radioButtonMenuItem.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent ev)
                {
                    try
                    {
                        Main.m_settings.setLookAndFeel(ev.getActionCommand());
                        int i, anzahl = lfMenu.getItemCount();
                        for (i=0; i< anzahl; i++)
                        {
                            JRadioButtonMenuItem menuItem = (JRadioButtonMenuItem)lfMenu.getItem(i);
                            menuItem.setSelected(menuItem.getActionCommand().equals(ev.getActionCommand()));
                        }
                    }
                    catch(Exception ex)
                    {
                    }
                    // Restart
                    if (JOptionPane.showConfirmDialog(Main.m_mainFrame, Main.getString("lookandfeel_restart_ask"), Main.getMessageBoxCaption(), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION)
                    {
                        try
                        {
                            String path = JClassPathHelper.getClassPath(this, true);
                            if (path != null)
                            {
                                doSaveSettings();
                                setVisible(false);
                                path = JPathHelper.addSeparator(path);
                                path += "jstart.jar";
                                String[] cmdArray = {JInfoHelper.getJavaExecutablePath(), "-jar", path};
                                if (Main.m_settings.isDebug())
                                {
                                    System.err.println(cmdArray[0]);
                                    System.err.println(path);
                                }
                                Runtime.getRuntime().exec(cmdArray);
                                System.exit(0);
                            }
                        }
                        catch(Exception ex)
                        {
                            setVisible(true);
                            System.err.println(ex);
                        }
                    }
                }
            });
            radioButtonMenuItem.setSelected(Main.m_settings.getLookAndFeel().equals(lfInfo.getClassName()));
            lfMenu.add(radioButtonMenuItem);
        }
        menu.add(lfMenu);

        // help menu
        menu = new JStatusMenu(Main.getString("menu_help"), m_statusBar);
        m_menuBar.add(menu);
        menuItem =  new JStatusMenuItem(Main.getString("menu_help_help"), Main.getString("statusbar_menu_help_help_help"), m_statusBar);
        menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0));
        menu.add(menuItem);
        menuItem.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ev)
            {
                JBrowser browser = new JBrowser(Main.m_mainFrame, Main.getString("help_caption"), getClass().getResource(Main.getString("helpfile")));
                browser.setVisible(true);
            }
        });

        menuItem =  new JStatusMenuItem(Main.getString("menu_help_web"), Main.getString("statusbar_menu_help_web_help"), m_statusBar);
        menu.add(menuItem);
        menuItem.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ev)
            {
                if (!JBrowserLaunch.openURL(m_homepage))
                {
                    JOptionPane.showMessageDialog(Main.m_mainFrame, String.format(Main.getString("msg_browserlaunch_failed"), m_homepage), Main.getMessageBoxCaption(), JOptionPane.PLAIN_MESSAGE, Main.m_icon32);
                }
            }
        });

        menu.addSeparator();

        menuItem =  new JStatusMenuItem(Main.getString("menu_help_update"), Main.getString("statusbar_menu_help_update_help"), m_statusBar);
        menu.add(menuItem);
        menuItem.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ev)
            {
                doCheckForUpdates(true);
            }
        });

        menu.addSeparator();

        menuItem =  new JStatusMenuItem(Main.getString("menu_help_about"), Main.getString("statusbar_menu_help_about_help"), m_statusBar);
        menu.add(menuItem);
        menuItem.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent ev)
            {
                StringBuilder strBuilder = new StringBuilder();
                strBuilder.append(Main.m_versionString);
                strBuilder.append("\n\n");
                strBuilder.append("Homepage:\n");
                strBuilder.append(m_homepage);
                strBuilder.append("\n\n");
                strBuilder.append(JInfoHelper.getJavaInfo(Main.m_settings.isDebug() ? 2 : 1));
                if (Main.m_settings.isDebug())
                    strBuilder.append("\n\nMemory: (total, free, max): " + Runtime.getRuntime().totalMemory() + ", " + Runtime.getRuntime().freeMemory() + ", " + Runtime.getRuntime().maxMemory());
                JOptionPane.showMessageDialog(Main.m_mainFrame, strBuilder.toString(), Main.getMessageBoxCaption(), JOptionPane.PLAIN_MESSAGE, Main.m_icon32);
            }
        });
    }
   
    public void doCheckForUpdates(boolean bManual)
    {
        boolean flag = false;
        try
        {
            if (bManual)
            setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
            URL url = new URL(m_updateFile);
            URLConnection urlCon = url.openConnection();
            urlCon.setDoInput(true);
            urlCon.setUseCaches(false);
            BufferedReader bufReader = new BufferedReader(new InputStreamReader(urlCon.getInputStream()));
            String str;
            StringBuilder strBuilder = new StringBuilder();
            while ((str = bufReader.readLine()) != null)
                strBuilder.append(str);
            bufReader.close();
            Pattern pat = Pattern.compile("jexifviewer_version=(\\d+)\\.(\\d+)");
            Matcher m = pat.matcher(strBuilder.toString());
            int minVer, majVer;
            int minVerThis, majVerThis;
            if (m.find())
            {
                majVer = Integer.parseInt(m.group(1));
                minVer = Integer.parseInt(m.group(2));
                pat = Pattern.compile("(\\d+)\\.(\\d+)");
                m = pat.matcher(Main.m_version);
                if (m.find())
                {
                    majVerThis = Integer.parseInt(m.group(1));
                    minVerThis = Integer.parseInt(m.group(2));
                    if (bManual)
                        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                    if (majVerThis < majVer || (majVerThis == majVer && minVerThis < minVer))
                    {
                        final String msg = String.format(Main.getString("upadte_msg"), majVerThis, minVerThis, majVer, minVer);
                        final JMainFrame main = this;
                        if (bManual)
                            JOptionPane.showMessageDialog(this, msg, Main.getMessageBoxCaption(), JOptionPane.WARNING_MESSAGE);
                        else
                            SwingUtilities.invokeLater(new Runnable()
                            {
                                public void run()
                                {
                                    JOptionPane.showMessageDialog(main, msg, Main.getMessageBoxCaption(), JOptionPane.WARNING_MESSAGE);
                                }
                            });
                    }
                    else if (bManual && (majVerThis > majVer || (majVerThis == majVer && minVerThis > minVer)))
                        JOptionPane.showMessageDialog(this, String.format(Main.getString("noupadte_beta_msg"), majVerThis, minVerThis), Main.getMessageBoxCaption(), JOptionPane.INFORMATION_MESSAGE);
                    else if (bManual)
                        JOptionPane.showMessageDialog(this, String.format(Main.getString("noupadte_msg"), majVerThis, minVerThis), Main.getMessageBoxCaption(), JOptionPane.INFORMATION_MESSAGE);
                    flag = true;
                }
            }
        }
        catch (IOException ex)
        {
            if (Main.m_settings.isDebug())
                System.err.println("Unable to get update infos");
        }
        if (bManual)
            setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
        if (!flag && bManual)
            JOptionPane.showMessageDialog(this, Main.getString("upadte_err"), Main.getMessageBoxCaption(), JOptionPane.ERROR_MESSAGE);
    }
   
    public void updateTitle(JIfdData data)
    {
        String str;
        if (data != null)
        {
            StringBuilder strBuilder = new StringBuilder();
            if (data.getFileSize() < 1024)
                strBuilder.append(Long.toString(data.getFileSize()));
            else if (data.getFileSize() < 1024*1024)
            {
                strBuilder.append(String.format("%1$.1f ", (float)data.getFileSize()/1024.0f));
                strBuilder.append(Main.getString("KByte"));
            }
            else if (data.getFileSize() < 1024*1024*1024)
            {
                strBuilder.append(String.format("%1$.2f ", (float)data.getFileSize()/(1024.0f*1024.0f)));
                strBuilder.append(Main.getString("MByte"));
            }
            str = data.getDigitizedDateTime();
            Date date = JIfdData.getDateFromString(str);
            if (date == null)
                date = data.getFileDate();
            SimpleDateFormat sdf = new SimpleDateFormat("EEEE");
            StringBuffer strBuf = new StringBuffer();
            sdf.format(date, strBuf, new FieldPosition(0));
            String strDate = strBuf + ", " + DateFormat.getDateInstance(DateFormat.LONG).format(date);
            String strTime = DateFormat.getTimeInstance(DateFormat.MEDIUM).format(date);
            String dirStr = "";
            if (m_slideshowTimer.isRunning())
            {
                switch (Main.m_settings.getSlideShowDirection())
                {
                    case 0: // up
                        dirStr = Main.getString("caption_slideshow_up");
                        break;
                    case 1: // down
                        dirStr = Main.getString("caption_slideshow_down");
                        break;
                    case 2: // random
                        dirStr = Main.getString("caption_slideshow_random");
                        break;
                }
            }
            else if (m_bSlideShowPause)
                dirStr = Main.getString("caption_slideshow_pause");

            str = String.format(Main.getString("caption_img"), Main.getString("caption"), data.getFullFileName(), strDate, strTime, strBuilder.toString(), m_imgView.getRealZoom()*100, m_slideshowTimer.isRunning() || m_bSlideShowPause ? Main.getString("caption_slideshow") + dirStr : "");
        }
        else
        {
            str = Main.getString("caption");
            if (m_slideshowTimer != null && m_slideshowTimer.isRunning())
            str += "  -  " + Main.getString("caption_slideshow");
        }
        str = str.trim();
        setTitle(str);
    }
   
    private void doSetPreload(int row)
    {
        if (Main.m_settings.isImgUsePreload())
        {
            m_preloadData[0] = null;
            m_preloadData[1] = null;
            if (Main.m_settings.getImgCacheSize() >= 3)
            {
                if (--row >= 0)
                    m_preloadData[0] = m_tableData.getRowData(row);
                row += 2;
            }
            else row++;
            if (row < m_tableData.getRowCount())
                m_preloadData[1] = m_tableData.getRowData(row);
        }
    }
   
    public void doSetImg()
    {
        ListSelectionModel lsm = m_table.getSelectionModel();
        int row = lsm.getMinSelectionIndex();
        JIfdData data = m_tableData.getRowData(row);
        if (!m_slideshowTimer.isRunning())
            doSetPreload(row);
        m_imgView.setJpg(data);
    }
   
    public void doInitTimers()
    {
        m_imgDisplayTimer = new Timer(Main.m_settings.getImgDisplayTimer(), new ActionListener()
        {
            public void actionPerformed(ActionEvent ev)
            {
                doSetImg();
            }
        });
        m_imgDisplayTimer.setRepeats(false);
        m_imgDisplayTimer.stop();

        m_fillListTimer = new Timer(Main.m_settings.getFillListTimer(), new ActionListener()
        {
            public void actionPerformed(ActionEvent ev)
            {
                String path = getPathFromTreePath(m_tree.getLeadSelectionPath());
                if (path != null)
                    doFillList(path);
                m_imgView.clearCache();
            }
        });
        m_fillListTimer.setRepeats(false);
        m_fillListTimer.stop();

        m_slideshowTimer = new Timer(Main.m_settings.getSlideShowTimer(), new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent ev)
            {
                if (!doSlideShowNext() && m_bImgFullSize)
                    toggleView();
            }
        });
        m_slideshowTimer.stop();
    }
   
    public int doSlideShowRandomNextRow()
    {
        int row = -1;
        if (m_slideShowRandomList.size() > 0)
        {
            int index = m_slideShowRandom.nextInt(m_slideShowRandomList.size());
            row = m_slideShowRandomList.isEmpty() ? -1 : m_slideShowRandomList.get(index);
            if (row >= 0)
            {
                m_slideShowRandomList.remove(index);
                if (Main.m_settings.isImgUsePreload())
                    m_imgView.preloadImg(m_tableData.getRowData(row));
            }
        }
        return row;
    }
   
    /**
     * @return true if next Image was selected false if no more images are in the list
     */   
    public boolean doSlideShowNext()
    {
        boolean flag = true;
        if (m_table.getRowCount() > 0)
        {
            int selRow = m_table.getSelectedRow();
            if (selRow >= 0)
            {
                switch(Main.m_settings.getSlideShowDirection())
                {
                    case 0: // up
                        selRow--;
                        break;
                    case 1: // down
                        selRow++;
                        break;
                    case 2: // Random
                        if ((selRow = m_slideShowRandomNextRow) < 0)
                        {
                            doSlideShowStop();
                            flag = false;
                        }
                        if ((m_slideShowRandomNextRow = doSlideShowRandomNextRow()) < 0)
                        {
                            if (Main.m_settings.getSlideShowLoop())
                            {
                                doSlideShowRandomInit();
                                m_slideShowRandomNextRow = doSlideShowRandomNextRow();
                            }
                        }
                        break;
                }
            }
            else selRow = Main.m_settings.getSlideShowDirection() != 0? 0 : m_table.getRowCount() - 1;
            if (Main.m_settings.getSlideShowDirection() != 2)
            {
                if (selRow >= m_table.getRowCount())
                {
                    if (Main.m_settings.getSlideShowLoop())
                        selRow = 0;
                    else
                    {
                        doSlideShowStop();
                        flag = false;
                    }
                }
                else if (selRow < 0)
                {
                    if (Main.m_settings.getSlideShowLoop())
                        selRow = m_table.getRowCount() - 1;
                    else
                    {
                        doSlideShowStop();
                        flag = false;
                    }
                }
            }

            if (selRow >= 0 && selRow < m_table.getRowCount())
            {
                selectRow(selRow, true);
                if (Main.m_settings.isDebug())
                    System.err.println("SlideShow next: " + selRow);
                if (flag && Main.m_settings.isImgUsePreload() && Main.m_settings.getSlideShowDirection() != 2)
                {
                    int nextRow = selRow + (Main.m_settings.getSlideShowDirection() == 1 ? 1 : -1);
                    if (nextRow >= m_table.getRowCount())
                        nextRow = 0;
                    if (nextRow < 0)
                        nextRow = m_table.getRowCount() - 1;
                    m_imgView.preloadImg(m_tableData.getRowData(nextRow));
                }
            }
        }
        else
        {
            doSlideShowStop();
            flag = false;
        }
      return flag;
    }
   
    public void doPreload()
    {
        if (m_preloadData[1] != null)
        {
            JIfdData ifd = m_preloadData[1];
            m_preloadData[1] = null;
            m_imgView.preloadImg(ifd);
            return;
        }
        if (m_preloadData[0] != null)
        {
            JIfdData ifd = m_preloadData[0];
            m_preloadData[0] = null;
            m_imgView.preloadImg(ifd);
        }
    }

    private void doSaveSettings()
    {  
        int i, anzahl = m_table.getColumnCount();
        Main.m_settings.m_cols = new short[anzahl];
        Main.m_settings.m_colWidth = new int[anzahl];
        TableColumnModel colModel = m_table.getColumnModel();
        for (i=0; i<anzahl; i++)
        {
            Main.m_settings.m_cols[i] = (short)m_table.convertColumnIndexToModel(i);
            TableColumn tableCol = colModel.getColumn(i);
            Main.m_settings.m_colWidth[i] = tableCol.getPreferredWidth();
        }

        // Custum tree entries
        DefaultTreeModel treeModel = (DefaultTreeModel)m_tree.getModel();
        JPathTreeNode root = (JPathTreeNode)treeModel.getRoot();
        anzahl = root.getChildCount();
        ArrayList<String> dirList = new ArrayList<String>();
        for (i=0; i<anzahl; i++)
        {
            JPathTreeNode treeData = (JPathTreeNode)root.getChildAt(i);
            if (!treeData.isDummy() && treeData.isCustom())
            dirList.add(treeData.getName());
        }
        anzahl = dirList.size();
        Main.m_settings.m_homeDir = new String[anzahl];
        for (i=0; i<anzahl; i++)
            Main.m_settings.m_homeDir[i] = dirList.get(i);

        doSaveSize();

        Main.m_settings.save(JPathHelper.addSeparator(System.getProperty("user.home")) + JSettings.SETTINGS_FILE);
    }

    private void doSaveSize()
    {
        // Size
        Main.m_settings.setExtendedState(getExtendedState());
       
        if (getExtendedState() != Frame.MAXIMIZED_BOTH)
        {
            Main.m_settings.setSize(getSize());
            Main.m_settings.setLocation(getLocation());
        }
       
        if (!m_bImgFullSize)
        {
            Main.m_settings.setHorDividerLocation((double)m_splitPaneHor.getDividerLocation() / (double)(m_splitPaneHor.getWidth() - m_dividerSizeHor));
            Main.m_settings.setVertDividerLocation((double)m_splitPaneVert.getDividerLocation() / (double)(m_splitPaneVert.getHeight() - m_dividerSizeVert));
        }
        else
        {
            Main.m_settings.setVertDividerLocation((double)m_splitPaneVert.getLastDividerLocation() / (double)(m_splitPaneHor.getWidth() - m_dividerSizeHor));
            Main.m_settings.setHorDividerLocation((double)m_splitPaneHor.getLastDividerLocation() / (double)(m_splitPaneVert.getHeight() - m_dividerSizeVert));
        }
    }
   
    private void doSetTableCols()
    {
        assert m_table.getColumnCount() == 0;
        int i;
        for (i=0; i<Main.m_settings.m_cols.length; i++)
        {
            TableColumn tblCol = new TableColumn();
            tblCol.setModelIndex(Main.m_settings.m_cols[i]);
            if (JExifDataModel.m_colTag[Main.m_settings.m_cols[i]] == JExifTag.GPSTAG_TAG_MAPLINK)
            {
                int w = new ImageIcon(Main.m_url_map).getIconWidth();
                tblCol.setPreferredWidth(w);
                tblCol.setMaxWidth(w);
                tblCol.setMinWidth(w);
            }
            else
                tblCol.setPreferredWidth(Main.m_settings.m_colWidth[i]);
            m_table.addColumn(tblCol);
        }
    }
   
    private void setTableHeaderValues()
    {
        int i, anzahl = m_table.getColumnCount();
        TableColumnModel colModel = m_table.getColumnModel();

        for (i=0; i<anzahl; i++)
        {
            TableColumn tableCol = colModel.getColumn(i);
            int colIndex = m_table.convertColumnIndexToModel(i);
            JLabel label = (JLabel)tableCol.getHeaderRenderer();
            if (label != null)
            {
                label.setIcon(m_tableData.getColIcon(colIndex));
            }
            else
            {
                // the new way
                String str = m_tableData.getColIconStr(colIndex);
//                if (str == null || str.isEmpty)
                if (str == null || str.length() == 0)
                    str = m_tableData.getColumnName(colIndex);
                else
                    str = String.format("<html><img src=\"%s\">&nbsp;%s</html>", str, m_tableData.getColumnName(colIndex));
                tableCol.setHeaderValue(str);
            }
        }
    }

    private void doInitTableCols()
    {
        setTableHeaderValues();
        m_tableData.sort();
    }
   
    private void doAddTableMenu()
    {
        m_table.addMouseListener(new MouseAdapter()
        {
            @Override
            public void mousePressed(MouseEvent ev)
            {
                doShowPopupMenu(ev);
            }

            @Override
            public void mouseReleased(MouseEvent ev)
            {
                doShowPopupMenu(ev);
            }

            protected void doShowPopupMenu(MouseEvent ev)
            {
                int row = m_table.rowAtPoint(ev.getPoint());
                if (row >= 0 && ev.isPopupTrigger())
                {
                    selectRow(row, false);
                    JStatusPopupMenu menu = new JStatusPopupMenu(m_statusBar);
                    JStatusMenuItem menuItem;
                    menuItem = new JStatusMenuItem(Main.getString("menu_table_rename"), Main.getString("statusbar_menutable_rename_help"), m_statusBar);
                    menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK));
                    menu.add(menuItem);
                    menuItem.addActionListener(new ActionListener()
                    {
                        public void actionPerformed (ActionEvent ev)
                        {
                            doRename();
                        }
                    });
                    menuItem = new JStatusMenuItem(Main.getString("menu_table_copy"), Main.getString("statusbar_menutable_copy_help"), m_statusBar);
                    menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_DOWN_MASK));
                    menu.add(menuItem);
                    menuItem.addActionListener(new ActionListener()
                    {
                        public void actionPerformed (ActionEvent ev)
                        {
                            doCopy(-1, false);
                        }
                    });
                    menuItem = new JStatusMenuItem(Main.getString("menu_table_move"), Main.getString("statusbar_menutable_move_help"), m_statusBar);
                    menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, InputEvent.CTRL_DOWN_MASK));
                    menu.add(menuItem);
                    menuItem.addActionListener(new ActionListener()
                    {
                        public void actionPerformed (ActionEvent ev)
                        {
                            doMove();
                        }
                    });
                    menuItem = new JStatusMenuItem(Main.getString("menu_table_del"), Main.getString("statusbar_menutable_del_help"), m_statusBar);
                    menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
                    menu.add(menuItem);
                    menuItem.addActionListener(new ActionListener()
                    {
                        public void actionPerformed (ActionEvent ev)
                        {
                            doDel(-1);
                        }
                    });

                    menu.addSeparator();
                    menuItem = new JStatusMenuItem(Main.getString("cancel"), Main.getString("statusbar_menutable_cancel_help"), m_statusBar);
                    menu.add(menuItem);
                    m_statusBar.saveText();
                    menu.show(ev.getComponent(), ev.getX(), ev.getY());
                }
            }
        });
    }
   
    private void doAddTableHeaderMenu()
    {
        JTableHeader tableHeader = m_table.getTableHeader();
        tableHeader.addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent ev)
            {
                int button = ev.getButton();
                if (button == MouseEvent.BUTTON1 || button == MouseEvent.BUTTON2)
                {
                    TableColumnModel colModel = m_table.getColumnModel();
                    int colIndex = colModel.getColumnIndexAtX(ev.getX());
                    colIndex = m_table.convertColumnIndexToModel(colIndex);
                    // if (JExifDataModel.m_colTag[colIndex] != JExifTag.GPSTAG_TAG_MAPLINK)
                    {
                        if (Main.m_settings.isDebug())
                            System.err.println("Sort:" + colIndex);

                        if (m_tableData.getSortCol() != colIndex)
                            m_tableData.setSortCol(colIndex);
                        else
                            m_tableData.setSortUp(!m_tableData.getSortUp());
                        setTableHeaderValues();

                        JIfdData jifdData = null;
                        int selRow = m_table.getSelectedRow();
                        if (selRow >= 0)
                            jifdData = m_tableData.getRowData(selRow);
                        m_tableData.sort();
                        if (jifdData != null && (selRow = m_tableData.findRow(jifdData)) >= 0)
                            selectRow(selRow, true);
                    }
                }
            }

            @Override
            public void mousePressed(MouseEvent ev)
            {
                doShowPopupMenu(ev);
            }

            @Override
            public void mouseReleased(MouseEvent ev)
            {
                doShowPopupMenu(ev);
            }

            protected void doShowPopupMenu(MouseEvent ev)
            {
                if (ev.isPopupTrigger())
                {
                    JPopupMenu menu = new JPopupMenu();
                    final MouseEvent mouseEv = ev;
                    JStatusMenuItem menuItem;
                    final TableModel tblModel = m_table.getModel();
                    if (tblModel.getColumnCount() != m_table.getColumnCount())
                    {
                        menuItem = new JStatusMenuItem(Main.getString("menu_tableheader_add"), Main.getString("statusbar_menutableheader_add_help"), m_statusBar);
                        menu.add(menuItem);
                        menuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                int i, anzahl = tblModel.getColumnCount(), colIndex, index = 0;
                                JColChooserData[] dataArray = new JColChooserData[anzahl - m_table.getColumnCount()];
                                for (i=0; i<anzahl; i++)
                                {
                                    colIndex = m_table.convertColumnIndexToView(i);
                                    if (colIndex == -1)
                                        dataArray[index++] = new JColChooserData(tblModel.getColumnName(i), i);
                                }
                                JColChooserDialog dia = new JColChooserDialog(Main.m_mainFrame, dataArray);
                                dia.setVisible(true);
                                if (dia.isOk())
                                {
                                    JColChooserData data = dia.getSelectedItem();
                                    TableColumn tblCol = new TableColumn();
                                    tblCol.setModelIndex(data.m_modelColIndex);
                                    TableColumnModel colModel = m_table.getColumnModel();
                                    colIndex = colModel.getColumnIndexAtX(mouseEv.getX());
                                    m_table.addColumn(tblCol);
                                    m_table.moveColumn(m_table.getColumnCount()-1, colIndex);
                                    if (JExifDataModel.m_colTag[data.m_modelColIndex] == JExifTag.GPSTAG_TAG_MAPLINK)
                                    {
                                        int w = new ImageIcon(Main.m_url_map).getIconWidth();
                                        tblCol.setPreferredWidth(w);
                                        tblCol.setMaxWidth(w);
                                        tblCol.setMinWidth(w);
                                    }
                                }
                            }
                        });
                    }
                    if (m_table.getColumnCount() > 1)
                    {
                        menuItem = new JStatusMenuItem(Main.getString("menu_tableheader_delete"), Main.getString("statusbar_menutableheader_delete_help"), m_statusBar);
                        menuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                TableColumnModel colModel = m_table.getColumnModel();
                                int colIndex = colModel.getColumnIndexAtX(mouseEv.getX());
                                TableColumn tblCol = colModel.getColumn(colIndex);
                                m_table.removeColumn(tblCol);
                                }
                        });
                        menu.add(menuItem);
                    }
                    menu.addSeparator();
                    menuItem = new JStatusMenuItem(Main.getString("cancel"), Main.getString("statusbar_menutableheader_cancel_help"), m_statusBar);
                    menu.add(menuItem);
                   // m_statusBar.saveText();
                    menu.show(ev.getComponent(), ev.getX(), ev.getY());
                }
            }
        });
    }
   
    private void selectRow(int row, boolean bScroll)
    {
        if (row >= 0 && row < m_tableData.getRowCount())
        {
            m_table.setRowSelectionInterval(row, row);
            if (bScroll)
            {
                Rectangle rect = m_table.getCellRect(row, 0, true);
                m_table.scrollRectToVisible(rect);
            }
        }
    }
   
    private void doAddTableMouseListener()
    {
        m_table.addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent ev)
            {
                if (ev.getClickCount() == 2)
                {
                    int row = m_table.rowAtPoint(ev.getPoint());
                    if (row >= 0)
                    {
                        doSetPreload(row);
                        int delay = m_imgDisplayTimer.getInitialDelay();
                        m_imgDisplayTimer.setInitialDelay(0);
                        m_imgDisplayTimer.restart();
                        m_imgDisplayTimer.setInitialDelay(delay);
                    }
                }
            }
        });
    }

    private String getPathFromTreePath(TreePath treePath)
    {
        if (treePath != null)
        {
            Object[] objArray = treePath.getPath();
            if (objArray != null)
            {
                StringBuilder strBuilder = new StringBuilder();
                for (Object item : objArray)
                {
                    JPathTreeNode pathTreeNode = (JPathTreeNode)item;
                    if (!pathTreeNode.isDummy())
                    {
                        JPathHelper.addSeparator(strBuilder);
                        strBuilder.append(pathTreeNode.getName());
                    }
                }
                return strBuilder.toString();
            }
        }
        return null;
    }

    protected static boolean hasJpegExtension(File file)
    {
        String ext = JPathHelper.getFileExtension(file);
        for (String item : Main.m_settings.m_jpgExtensions)
        {
            if (item.equals(ext.toLowerCase()))
                return true;
        }
        return false;
    }
   
    private void doFillList(final String path)
    {
        if (Main.m_settings.isDebug()) System.err.println("FillList: " + path);
        if (m_fillListThread != null)
        {
            m_fillListThread.interrupt();
            try
            {
                m_fillListThread.join();
            }
            catch (Exception ex)
            {}
        }
        m_tableData.removeAll();
        m_fillListThread = new Thread()
        {
            @Override
            public void run()
            {
                int count = 0, count2 = 0;
                File file = new File(path);
                final File[] fileArray = file.listFiles(new JFileNameFilter());
                SwingUtilities.invokeLater( new Runnable()
                {
                    public void run()
                        {m_progBar.setString(null);}
                });
                final ArrayList<JIfdData> arrayList = new ArrayList<JIfdData>();
                if (fileArray != null)
                {
                    for (File item : fileArray)
                    {
                        if (isInterrupted())
                            break;
                        final int c = count2++;
                        SwingUtilities.invokeLater( new Runnable()
                        {
                            public void run()
                            {m_progBar.setValue((c*1000)/fileArray.length);}
                        });
                        if (!item.isDirectory() && !item.isHidden() && item.canRead())
                        {
                            if (Main.m_settings.isDebug())
                                System.err.println("Reading: " + item.getPath());
                            final JIfdData data = new JIfdData();
                            if (data.readFromFile(item) || Main.m_settings.isDisplayAllInages())
                            {
                                count++;
                                arrayList.add(data);
                            }
                        }
                    }
                }
                if (!isInterrupted())
                {
                    String str;
                    if (count != 0)
                    str = String.format(Main.getString("statusbar_filllist_items"), count);
                    else
                    str = Main.getString("statusbar_filllist_noitems");
                    final String message = str;
                    SwingUtilities.invokeLater( new Runnable()
                    {
                        public void run()
                        {
                           m_tableData.addData(arrayList);
                           m_tableData.sort();
                           m_statusBar.setText(message);
                           m_progBar.reset();
                           setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                           m_fillListThread = null;
                        }
                    });
                }
            }
        };
        m_statusBar.setText(Main.getString("statusbar_filllist_start"));
        m_progBar.setString(Main.getString("progressbar_filllist_scanningdir"));
        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        m_fillListThread.start();
    }

        private void doAddTreeSelectionListener()
        {
        m_tree.addTreeSelectionListener(new TreeSelectionListener()
        {
            public void valueChanged(TreeSelectionEvent ev)
            {
            if (!m_bTreePopupMenu)
            {
                TreePath treePath = ev.getPath();
                if (treePath != null)
                {
                m_fillListTimer.restart();
                doSlideShowStop();
                }
            }
            }
        });
    }

    private void doExpandTree(final TreeExpansionEvent ev) throws ExpandVetoException
    {
        final TreePath treePath = ev.getPath();
        if (treePath != null)
        {
            final JPathTreeNode thisNode = (JPathTreeNode)treePath.getLastPathComponent();
            if (!thisNode.isDummy())
            {
                if (m_expandThread == null)
                {
                    m_expandThread = new Thread()
                    {
                        @Override
                        public void run()
                        {
                            thisNode.addChilds(treePath);
                            final DefaultTreeModel treeModel = (DefaultTreeModel)((JTree)ev.getSource()).getModel();
                            SwingUtilities.invokeLater( new Runnable()
                            {
                                public void run()
                                {
                                    treeModel.nodeStructureChanged(thisNode);
                                    m_progBar.reset();
                                    m_statusBar.setText(String.format(Main.getString("statusbar_opendir_items"), thisNode.getChildCount()));
                                    setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                                    m_expandThread = null;
                                }
                            });
                        }
                    };
                    m_progBar.setString(Main.getString("progressbar_opendir_scanningdir"));
                    m_statusBar.setText(Main.getString("statusbar_opendir_start"));
                    setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
                    m_expandThread.start();
                }
                else throw new ExpandVetoException(ev);
            }
            else throw new ExpandVetoException(ev);
        }
    }
   
    private void doAddTreeExpandListener()
    {
        m_tree.addTreeWillExpandListener(new TreeWillExpandListener()
        {
            public void treeWillExpand(TreeExpansionEvent evthrows ExpandVetoException
            {
                doExpandTree(ev);
            }

            public void treeWillCollapse(TreeExpansionEvent ev)
            {
                TreePath treePath = ev.getPath();
                if (treePath != null)
                {
                    JPathTreeNode thisNode = (JPathTreeNode)treePath.getLastPathComponent();
                    thisNode.removeAllChildren();
                    thisNode.add(new JPathTreeNode("", false, true));
                    ((DefaultTreeModel)m_tree.getModel()).nodeStructureChanged(thisNode);
                }
            }
        });
    }
   
    private void doAddTreePopupMenu()
    {
        m_tree.addMouseListener(new MouseAdapter()
        {
            @Override
            public void mousePressed(MouseEvent ev)
            {
                doShowPopupMenu(ev);
            }

            @Override
            public void mouseReleased(MouseEvent ev)
            {
                doShowPopupMenu(ev);
            }

            protected void doShowPopupMenu(MouseEvent ev)
            {
                if (ev.isPopupTrigger())
                {
                    final TreePath treePath = m_tree.getPathForLocation(ev.getX(), ev.getY());
                    if (treePath != null)
                    {
                        final JPathTreeNode treeNode = (JPathTreeNode)treePath.getLastPathComponent();
                        if (!treeNode.isDummy())
                        {
                            final TreePath selTreePath = m_tree.getLeadSelectionPath();
                            m_bTreePopupMenu = true;
                            m_tree.setSelectionPath(treePath);
                            m_tree.scrollPathToVisible(treePath);
                            JStatusPopupMenu menu = new JStatusPopupMenu(m_statusBar);
                            menu.addPopupMenuListener(new PopupMenuAdapter()
                            {
                                @Override
                                public void popupMenuWillBecomeInvisible(PopupMenuEvent ev)
                                {
                                    m_bTreePopupMenu = false;
                                }
                            });
                            JStatusMenuItem menuItem;
                            final DefaultTreeModel treeModel = (DefaultTreeModel)m_tree.getModel();
                            if (treeNode.isCustom())
                            {
                                menuItem = new JStatusMenuItem(Main.getString("menu_tree_remove"), Main.getString("statusbar_menutree_remove_help"), m_statusBar);
                                menu.add(menuItem);
                                menuItem.addActionListener(new ActionListener()
                                {
                                    public void actionPerformed (ActionEvent ev)
                                    {
                                        DefaultMutableTreeNode parent = (DefaultMutableTreeNode)treeNode.getParent();
                                        parent.remove(treeNode);
                                        treeModel.nodeStructureChanged(parent);
                                        /*
                                        JPathTreeNode root = (JPathTreeNode)treeModel.getRoot();
                                        ArrayList<TreePath> treePathList = new ArrayList<TreePath>();
                                        root.addExpandedChilds(m_tree, treePathList);
                                        for (TreePath item : treePathList)
                                        {
                                            m_tree.expandPath(item);
                                        }
                                         */
                                        // if (selTreePath != null) m_tree.scrollPathToVisible(selTreePath);
                                    }
                                });
                            }
                            else
                            {
                                menuItem = new JStatusMenuItem(Main.getString("menu_tree_add"), Main.getString("statusbar_menutree_add_help"), m_statusBar);
                                menu.add(menuItem);
                                menuItem.addActionListener(new ActionListener()
                                {
                                    public void actionPerformed (ActionEvent ev)
                                    {
                                        DefaultMutableTreeNode root = (DefaultMutableTreeNode)treeModel.getRoot();
                                        String path = getPathFromTreePath(treePath);
                                        JPathTreeNode newNode = new JPathTreeNode(path, !JPathTreeNode.hasChilds(new File(path)), false, true);
                                        root.insert(newNode, 0);
                                        treeModel.nodeStructureChanged(root);
                                        m_tree.scrollPathToVisible(selTreePath);
                                        m_tree.scrollPathToVisible(new TreePath(newNode.getPath()));
                                    }
                                });
                            }
                            menu.addSeparator();
                            menuItem = new JStatusMenuItem(Main.getString("menu_tree_batch"), Main.getString("statusbar_menutree_batch_help"), m_statusBar);
                            menu.add(menuItem);
                            menuItem.addActionListener(new ActionListener()
                            {
                                public void actionPerformed (ActionEvent ev)
                                {
                                    m_batchData.m_srcFolder = getPathFromTreePath(treePath);
                                    doBatch();
                                }
                            });
                            menu.addSeparator();
                            menuItem = new JStatusMenuItem(Main.getString("cancel"), Main.getString("statusbar_menutree_cancel_help"), m_statusBar);
                            menu.add(menuItem);
                            menu.show(ev.getComponent(), ev.getX(), ev.getY());
                        }
                    }
                }
            }
        });
    }
   
    private void doAddImgListener()
    {
        m_imgView.addMouseWheelListener(new MouseWheelListener()
        {
            public void mouseWheelMoved(MouseWheelEvent ev)
            {
                int orientation = 0;
                orientation = JImgView.getNextOrientation(m_imgView.getOrientation(), ev.getWheelRotation() >= 0);
                if (orientation != 0)
                {
                    m_imgView.setOrientation(orientation);
                    updateTitle(m_imgView.getIfdData());
                }
            }
        });

        m_imgView.addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent ev)
            {
                if (m_imgView.isImage())
                {
                    if (ev.getButton() == MouseEvent.BUTTON1)
                    {
                        if (ev.getClickCount() == 2)
                            toggleView();
                    }
                    else if (ev.getButton() == MouseEvent.BUTTON2)
                    {
                        int orientation = JImgView.getNextFlipOrientation(m_imgView.getOrientation());
                        if (orientation != 0)
                            m_imgView.setOrientation(orientation);
                    }
                    else if (ev.getButton() == MouseEvent.BUTTON3)
                    {
                        JPopupMenu menu = new JPopupMenu();
                        menu.addPopupMenuListener(new PopupMenuAdapter()
                        {
                            @Override
                            public void popupMenuWillBecomeInvisible(PopupMenuEvent ev)
                            {
                                m_statusBar.setText(null);
                            }

                        });
                        JMenuItem menuItem;
                        menuItem = new JStatusMenuItem(Main.getString("menu_img_rotate_90"), Main.getString("statusbar_menuimg_rotate90_help"), m_statusBar);
                        menu.add(menuItem);
                        menuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                int orientation = JImgView.getNextOrientation(m_imgView.getOrientation(), true);
                                if (orientation != 0)
                                    m_imgView.setOrientation(orientation);
                            }
                        });
                        menuItem = new JStatusMenuItem(Main.getString("menu_img_rotate_-90"), Main.getString("statusbar_menuimg_rotate-90_help"), m_statusBar);
                        menu.add(menuItem);
                        menuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                int orientation = JImgView.getNextOrientation(m_imgView.getOrientation(), false);
                                if (orientation != 0)
                                    m_imgView.setOrientation(orientation);
                            }
                        });
                        menuItem = new JStatusMenuItem(Main.getString("menu_img_rotate_180"), Main.getString("statusbar_menuimg_rotate180_help"), m_statusBar);
                        menu.add(menuItem);
                        menuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                int orientation = JImgView.getNextOrientation(m_imgView.getOrientation(), true);
                                orientation = JImgView.getNextOrientation(orientation, true);
                                if (orientation != 0)
                                    m_imgView.setOrientation(orientation);
                            }
                        });
                        menuItem = new JStatusMenuItem(Main.getString("menu_img_rotate_flip"), Main.getString("statusbar_menuimg_rotateflip_help"), m_statusBar);
                        menu.add(menuItem);
                        menuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                int orientation = JImgView.getNextFlipOrientation(m_imgView.getOrientation());
                                if (orientation != 0)
                                    m_imgView.setOrientation(orientation);
                            }
                        });
                        if (m_imgView.getCustomOrientation() != 0)
                        {
                            menu.addSeparator();
                            menuItem = new JStatusMenuItem(Main.getString("menu_img_rotate_original"), Main.getString("statusbar_menuimg_original_help"), m_statusBar);
                            menu.add(menuItem);
                            menuItem.addActionListener(new ActionListener()
                            {
                                public void actionPerformed (ActionEvent ev)
                                {
                                    m_imgView.setOrientation(0);
                                }
                            });
                        }
                        menu.addSeparator();
                        JMenu sizeMenu = new JMenu(Main.getString("menu_img_size"));
                        float zoom = m_imgView.getZoom();

                        JStatusRadioButtonMenuItem radioMenuItem = new JStatusRadioButtonMenuItem(Main.getString("menu_img_size_fit"), Main.getString("statusbar_menuimg_size_fit_help"), m_statusBar);
                        radioMenuItem.setSelected(zoom == 0.0f);
                        radioMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK));

                        radioMenuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                m_imgView.resetZoom();
                            }
                        });
                        sizeMenu.add(radioMenuItem);

                        radioMenuItem = new JStatusRadioButtonMenuItem(Main.getString("menu_img_size_8"), Main.getString("statusbar_menuimg_size_8_help"), m_statusBar);
                        radioMenuItem.setSelected(zoom == 8.0f);
                        radioMenuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                m_imgView.setZoom(8.0f);
                            }
                        });
                        sizeMenu.add(radioMenuItem);

                        radioMenuItem = new JStatusRadioButtonMenuItem(Main.getString("menu_img_size_4"), Main.getString("statusbar_menuimg_size_4_help"), m_statusBar);
                        radioMenuItem.setSelected(zoom == 4.0f);
                        radioMenuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                m_imgView.setZoom(4.0f);
                            }
                        });
                        sizeMenu.add(radioMenuItem);

                        radioMenuItem = new JStatusRadioButtonMenuItem(Main.getString("menu_img_size_2"), Main.getString("statusbar_menuimg_size_2_help"), m_statusBar);
                        radioMenuItem.setSelected(zoom == 2.0f);
                        radioMenuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                m_imgView.setZoom(2.0f);
                            }
                        });
                        sizeMenu.add(radioMenuItem);

                        radioMenuItem = new JStatusRadioButtonMenuItem(Main.getString("menu_img_size_1"), Main.getString("statusbar_menuimg_size_1_help"), m_statusBar);
                        radioMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_MULTIPLY, InputEvent.CTRL_DOWN_MASK));
                        radioMenuItem.setSelected(zoom == 1.0f);
                        radioMenuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                m_imgView.setZoom(1.0f);
                            }
                        });
                        sizeMenu.add(radioMenuItem);

                        radioMenuItem = new JStatusRadioButtonMenuItem(Main.getString("menu_img_size_075"), Main.getString("statusbar_menuimg_size_075_help"), m_statusBar);
                        radioMenuItem.setSelected(zoom == 0.75f);
                        radioMenuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                m_imgView.setZoom(0.75f);
                            }
                        });
                        sizeMenu.add(radioMenuItem);

                        radioMenuItem = new JStatusRadioButtonMenuItem(Main.getString("menu_img_size_050"), Main.getString("statusbar_menuimg_size_050_help"), m_statusBar);
                        radioMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DIVIDE, InputEvent.CTRL_DOWN_MASK));
                        radioMenuItem.setSelected(zoom == 0.5f);
                        radioMenuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                m_imgView.setZoom(0.5f);
                            }
                        });
                        sizeMenu.add(radioMenuItem);

                        radioMenuItem = new JStatusRadioButtonMenuItem(Main.getString("menu_img_size_025"), Main.getString("statusbar_menuimg_size_025_help"), m_statusBar);
                        radioMenuItem.setSelected(zoom == 0.25f);
                        radioMenuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                m_imgView.setZoom(.25f);
                            }
                        });
                        sizeMenu.add(radioMenuItem);

                        radioMenuItem = new JStatusRadioButtonMenuItem(Main.getString("menu_img_size_0125"), Main.getString("statusbar_menuimg_size_0125_help"), m_statusBar);
                        radioMenuItem.setSelected(zoom == 0.125f);
                        radioMenuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                m_imgView.setZoom(.125f);
                            }
                        });
                        sizeMenu.add(radioMenuItem);

                        radioMenuItem = new JStatusRadioButtonMenuItem(Main.getString("menu_img_size_00625"), Main.getString("statusbar_menuimg_size_00625_help"), m_statusBar);
                        radioMenuItem.setSelected(zoom == 0.0625f);
                        radioMenuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                m_imgView.setZoom(.0625f);
                            }
                        });
                        sizeMenu.add(radioMenuItem);

                        sizeMenu.addSeparator();

                        menuItem = new JStatusMenuItem(Main.getString("menu_img_size_down"), Main.getString("statusbar_menuimg_size_down_help"), m_statusBar);
                        menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_SUBTRACT, InputEvent.CTRL_DOWN_MASK));
                        menuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                m_imgView.setZoomDown();
                            }
                        });
                        sizeMenu.add(menuItem);

                        menuItem = new JStatusMenuItem(Main.getString("menu_img_size_up"), Main.getString("statusbar_menuimg_size_up_help"), m_statusBar);
                        menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ADD, InputEvent.CTRL_DOWN_MASK));
                        menuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                m_imgView.setZoomUp();
                            }
                        });
                        sizeMenu.add(menuItem);

                        menu.add(sizeMenu);
                        menu.addSeparator();
                        menuItem = new JStatusMenuItem(Main.getString("menu_img_print"), Main.getString("statusbar_menuimg_print_help"), m_statusBar);
                        menu.add(menuItem);
                        menuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                final PrinterJob printerJob = PrinterJob.getPrinterJob();
                                if (m_pageFormat == null) m_pageFormat = printerJob.defaultPage();
                                PageFormat pf = printerJob.pageDialog(m_pageFormat);
                                if (pf != m_pageFormat)
                                {
                                    m_pageFormat = pf;
                                    printerJob.setPrintable(m_imgView, m_pageFormat);
                                    printerJob.setJobName(Main.getString("caption"));
                                    if (printerJob.printDialog())
                                    {
                                        Thread thread = new Thread ()
                                        {
                                            @Override
                                            public void run()
                                            {
                                                try
                                                {
                                                    printerJob.print();
                                                }
                                                catch (PrinterException ex)
                                                {}
                                                finally
                                                {
                                                    SwingUtilities.invokeLater( new Runnable()
                                                    {
                                                        public void run()
                                                        {
                                                            m_statusBar.setText(Main.getString("statusbar_print_end"));
                                                            setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                                                        }
                                                    });
                                                }
                                            }
                                        };
                                        m_statusBar.setText(Main.getString("statusbar_print_start"));
                                        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
                                        thread.start();
                                    }
                                }
                            }
                        });
                        final JIfdData ifdData = m_imgView.getIfdData();
                        if (ifdData != null && m_imgView.getCustomOrientation() != 0)
                        {
                            menuItem = new JStatusMenuItem(Main.getString("menu_img_save"), Main.getString("statusbar_menuimg_save_help"), m_statusBar);
                            menuItem.addActionListener(new ActionListener()
                            {
                                public void actionPerformed (ActionEvent ev)
                                {
                                    m_imgView.saveOrientation(true);
                                }
                            });
                            menu.addSeparator();
                            menu.add(menuItem);
                        }
                        menu.addSeparator();
                        menuItem = new JStatusMenuItem(Main.getString("menu_img_export"), Main.getString("statusbar_menuimg_export_help"), m_statusBar);                        menu.add(menuItem);
                        menuItem.addActionListener(new ActionListener()
                        {
                            public void actionPerformed (ActionEvent ev)
                            {
                                m_imgView.export();
                            }
                        });
                        menu.addSeparator();

                        menuItem = new JStatusMenuItem(Main.getString("cancel"), Main.getString("statusbar_menuimg_cancel_help"), m_statusBar);
                        menu.add(menuItem);
                        m_statusBar.saveText();
                        menu.show(m_imgView, ev.getX(), ev.getY());
                    }
                }
            }
        });
    }
   
    public void toggleView()
    {
        if (m_bImgFullSize)
        {
            if (m_bInFullScreenMode)
            {
                setVisible(false);
                dispose();

                GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(null);
                getRootPane().setWindowDecorationStyle(m_dekoStyle);
                setUndecorated(m_bUndecorated);

                /*
                Container contentPane = getContentPane();
                contentPane.remove(m_imgScrollPane);
                m_splitPaneVert.setBottomComponent(m_imgScrollPane);
                contentPane.add(m_splitPaneHor, BorderLayout.CENTER);
                */
       
                m_bInFullScreenMode = false;
            }

            m_imgView.setZoom(m_zoom);

            ToolTipManager.sharedInstance().setEnabled(true);
            setJMenuBar(m_menuBar);
            m_statusBar.setVisible(true);
            m_progBar.setVisible(true);

            m_splitPaneVert.setTopComponent(m_treeScrollPane);
            m_splitPaneHor.setRightComponent(m_listScrollPane);

            m_bImgFullSize = false;

            // if (Main.m_settings.getExtendedState() != MAXIMIZED_BOTH)
                setResizable(true);

            Main.setSize();

            setVisible(true);

            requestFocus();
            m_table.requestFocus();

            Timer timer = new Timer(150, new ActionListener()
            {
                public void actionPerformed(ActionEvent ev)
                {
                    if (Main.m_settings.getExtendedState() == MAXIMIZED_BOTH)
                        setExtendedState(JFrame.MAXIMIZED_BOTH);
                    Timer timer = new Timer(150, new ActionListener()
                    {
                        public void actionPerformed(ActionEvent ev)
                        {
                            m_splitPaneVert.setDividerSize(m_dividerSizeVert);
                            m_splitPaneHor.setDividerSize(m_dividerSizeHor);
                            m_splitPaneVert.setDividerLocation(m_dividerLocationVert);
                            m_splitPaneHor.setDividerLocation(m_dividerLocationHor);
                        }
                    });
                    timer.setRepeats(false);
                    timer.start();
                }
            });
            timer.setRepeats(false);
            timer.start();

            int selRow = m_table.getSelectedRow();
            if (selRow >= 0)
            {
                Rectangle rect = m_table.getCellRect(selRow, 0, true);
                m_table.scrollRectToVisible(rect);
            }
        }
        else
        {
            /*
            if (getExtendedState() == JFrame.MAXIMIZED_BOTH)
                setExtendedState(JFrame.NORMAL);
            */
            m_dividerSizeVert = m_splitPaneVert.getDividerSize();
            m_dividerSizeHor = m_splitPaneHor.getDividerSize();
            m_dividerLocationHor = (double)m_splitPaneHor.getDividerLocation() / (double)(m_splitPaneHor.getWidth() - m_dividerSizeHor);
            m_dividerLocationVert = (double)m_splitPaneVert.getDividerLocation() / (double)(m_splitPaneVert.getHeight() - m_dividerSizeVert);

            ToolTipManager.sharedInstance().setEnabled(false);
            setJMenuBar(null);
            m_statusBar.setVisible(false);
            m_progBar.setVisible(false);
           
            m_splitPaneVert.setTopComponent(null);
            m_splitPaneHor.setRightComponent(null);
            m_splitPaneVert.setDividerSize(0);
            m_splitPaneVert.setDividerLocation(0.0);
            m_splitPaneHor.setDividerSize(0);
            m_splitPaneHor.setDividerLocation(1.0);
           
            if (Main.m_settings.getUseFullScreenMode() || getExtendedState() != MAXIMIZED_BOTH)
                setResizable(false);

            m_zoom = m_imgView.getZoom();
            m_imgView.resetZoom();

            if (GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().isFullScreenSupported() && Main.m_settings.getUseFullScreenMode())
            {
                doSaveSize();
               
                setVisible(false);
                dispose();

                /*
                Container contentPane = getContentPane();
                contentPane.remove(m_splitPaneHor);
                m_splitPaneVert.setBottomComponent(null);
                contentPane.add(m_imgScrollPane, BorderLayout.CENTER);
                */

                m_bUndecorated = isUndecorated();
                m_dekoStyle = getRootPane().getWindowDecorationStyle();

                setUndecorated(true);
               
                getRootPane().setWindowDecorationStyle(JRootPane.NONE);
                GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(Main.m_mainFrame);
                m_bInFullScreenMode = true;
            }
            m_bImgFullSize = true;

            validate();
            setVisible(true);
            requestFocus();
            try
            {
                Robot robot = new Robot();
                robot.mouseMove(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getWidth() + 48, -48);
            }
            catch(AWTException ex)
            {}
        }
    }
   
    public void updateTableItem(JIfdData ifdData)
    {
        int row = m_tableData.findRow(ifdData.getFilePath());
        if (row >= 0)
        {
            m_tableData.getRowData(row).readFromFile(ifdData.getFilePath());
            m_tableData.fireTableRowsUpdated(row, row);
        }
    }
   
    public void selectNextItem(boolean bUp)
    {
        ListSelectionModel lsm = m_table.getSelectionModel();
        int row = lsm.getMinSelectionIndex();
        if (row >= 0)
        {
            if (bUp) row--;
            else row++;
            if (row >= 0 && row < m_tableData.getRowCount())
                lsm.setSelectionInterval(row, row);
        }
    }

    private void doBatch()
    {
        JBatchDialog dia = new JBatchDialog(Main.m_mainFrame, m_batchData);
        if (dia.doModal())
        {
            doBatch(m_batchData);
        }
    }

    private void doBatchCollect(String baseFolder, JBatchData data, ArrayList<File> fileArray)
    {
        File file = new File(baseFolder);
        baseFolder = JPathHelper.addSeparator(baseFolder);
        String[] array = file.list(data);
        for (String item : array)
        {
            item = baseFolder + item;
            File inFile = new File(item);
            if (inFile.isDirectory())
            {
                if (data.m_bRecursive)
                    doBatchCollect(item, data, fileArray);
            }
            else
                fileArray.add(new File(item));
        }
    }

    private void doBatch(final JBatchData data)
    {
        data.m_targetFolder = JPathHelper.addSeparator(data.m_targetFolder);
        final JWaitDialog waitDialog = new JWaitDialog(this, Main.getString("wait_scan_caption"), null);
        final ArrayList<File> fileArray = new ArrayList<File>();
        waitDialog.setIndeterminate(true);
        Thread thread = new Thread(new Runnable()
        {
            public void run()
            {
                doBatchCollect(data.m_srcFolder, data, fileArray);
                SwingUtilities.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        waitDialog.stop();
                    }
                });
            }
        });
        thread.start();
        waitDialog.start();

        final JWaitDialog waitDialog_convert = new JWaitDialog(this, Main.getString("wait_convert_caption"), Main.getString("cancel"));
        waitDialog_convert.setRange(0, fileArray.size());
        thread = new Thread(new Runnable()
        {
            public void run()
            {
                int count = 0;
                String template = Main.getString("wait_convert");
                for (File file : fileArray)
                {
                    if (waitDialog_convert.wasCancelled())
                        break;
                    String path = file.getPath();
                    String newFile = data.m_targetFolder + path.substring(data.m_srcFolder.length()+1, path.length());
                    newFile = newFile.substring(0, newFile.length() - JPathHelper.getFileExtension(newFile).length());
                    newFile += data.getTargetExtension();
                    String fileName = JPathHelper.getBaseFileName(newFile);
                    String dirName = JPathHelper.addSeparator(JPathHelper.getFolder(newFile));
                    String extName = JPathHelper.getFileExtension(newFile);
                    newFile = dirName + data.m_targetTemplate.replaceAll("%1", fileName) + "." + extName;
                    File targetFile = new File(newFile);
                    File srcFile = new File(path);
                    if (!srcFile.equals(targetFile))
                    {
                        boolean flag = false;
                        File targetDir = new File(JPathHelper.getFolder(targetFile));
                        if (targetDir.exists() ? true : targetDir.mkdirs())
                        {
                            try
                            {
                                JIfdData ifd = new JIfdData(srcFile);
                                BufferedImage bi = ImageIO.read(srcFile);
                                switch (data.m_targetFormat)
                                {
                                    case JBatchData.JPG_FORMAT:
                                        m_imgView.saveJPG(targetFile, bi, ifd, data.m_scaleFactor, data.m_quality, data.m_bOptimizedHuffmanTable);
                                        break;
                                    case JBatchData.PNG_FORMAT:
                                        m_imgView.savePNG(targetFile, bi, ifd, data.m_scaleFactor);
                                        break;
                                    case JBatchData.BMP_FORMAT:
                                        m_imgView.saveBMP(targetFile, bi, ifd, data.m_scaleFactor);
                                        break;
                                }
                            }
                            catch(IOException ex)
                            {}
                        }
                        else if (Main.m_settings.isDebug())
                            System.err.println("Unable to ceate directory: " + targetDir);
                    }
                    else if (Main.m_settings.isDebug())
                        System.err.println("Source and target are identical: " + targetFile);
                    final int _count = count++;
                    final String str = String.format(template, fileName + "." + extName);
                    SwingUtilities.invokeLater(new Runnable()
                    {
                        public void run()
                        {
                            waitDialog_convert.notify(new ProgNotify(ProgNotify.RUN, _count, str));
                        }
                    });
                }
                SwingUtilities.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        waitDialog_convert.stop();
                    }
                });
            }
        });
        thread.start();
        waitDialog_convert.start();
    }
}

class JFileNameFilter implements FilenameFilter
{
    public boolean accept(File dir, String name)
    {
        return JMainFrame.hasJpegExtension(new File(dir, name));
    }
}
TOP

Related Classes of jexifviewer.JFileNameFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.