/*
 * File:     ElanFrame2.java
 * Project:  MPI Linguistic Application
 * Date:     03 April 2006
 *
 * Copyright (C) 2001-2006  Max Planck Institute for Psycholinguistics
 *
 * 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 even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package mpi.eudico.client.annotator;

import mpi.eudico.client.annotator.commands.BackupCA;
import mpi.eudico.client.annotator.commands.Command;
import mpi.eudico.client.annotator.commands.CommandAction;
import mpi.eudico.client.annotator.commands.ELANCommandFactory;
import mpi.eudico.client.annotator.commands.StoreCommand;

import mpi.eudico.client.annotator.grid.GridViewer;

import mpi.eudico.client.annotator.gui.ElanMenuItem;
import mpi.eudico.client.annotator.gui.ImportShoeboxWAC;
import mpi.eudico.client.annotator.gui.MultiFileChooser;

import mpi.eudico.client.annotator.linkedmedia.LinkedFileDescriptorUtil;
import mpi.eudico.client.annotator.linkedmedia.MediaDescriptorUtil;

import mpi.eudico.client.annotator.player.JMFGraphicMediaPlayer;

import mpi.eudico.client.annotator.svg.SVGPrefs;

import mpi.eudico.client.annotator.util.ElanFileFilter;
import mpi.eudico.client.annotator.util.FileUtility;

import mpi.eudico.client.annotator.viewer.InterlinearViewer;
import mpi.eudico.client.annotator.viewer.SubtitleViewer;
import mpi.eudico.client.annotator.viewer.TextViewer;
import mpi.eudico.client.annotator.viewer.TimeLineViewer;
import mpi.eudico.client.annotator.viewer.TimeSeriesViewer;

import mpi.eudico.client.mac.MacApplicationListener;

import mpi.eudico.p2p.*;

import mpi.eudico.server.corpora.clom.Tier;
import mpi.eudico.server.corpora.clom.Transcription;

import mpi.eudico.server.corpora.clomimpl.abstr.MediaDescriptor;
import mpi.eudico.server.corpora.clomimpl.abstr.TranscriptionImpl;
import mpi.eudico.server.corpora.clomimpl.dobes.ACM23TranscriptionStore;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import java.io.File;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.ButtonGroup;
import javax.swing.ComponentInputMap;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.JTextComponent;
import javax.swing.text.Keymap;


/**
 * DOCUMENT ME! $Id: ElanFrame2.java,v 1.18 2006/04/03 16:04:25 hasloe Exp $
 *
 * @author $Author: hasloe $
 * @version $Revision: 1.18 $
 */
public class ElanFrame2 extends JFrame implements ActionListener,
    ElanLocaleListener, MacApplicationListener {
    private static int frameCount = 0;
    private static boolean exitAllowed = false;
    private static Vector allEAFPaths;
    private static Vector allElanFrames;

    // load some keybindings for the Mac
    static {
        if (System.getProperty("os.name").indexOf("Mac") > -1) {
            JTextComponent.KeyBinding[] bind = new JTextComponent.KeyBinding[] {
                    new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(
                            KeyEvent.VK_C,
                            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
                        DefaultEditorKit.copyAction),
                    new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(
                            KeyEvent.VK_X,
                            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
                        DefaultEditorKit.cutAction),
                    new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(
                            KeyEvent.VK_V,
                            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
                        DefaultEditorKit.pasteAction),
                    new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(
                            KeyEvent.VK_A,
                            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
                        DefaultEditorKit.selectAllAction)
                };

            JTextComponent comp = new JTextField();
            Keymap map = JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP);
            JTextComponent.loadKeymap(map, bind, comp.getActions());
        }
    }

    private Transcription transcriptionForThisFrame;
    private JMenuBar menuBar;
    private JMenu menuFile;
    private JMenuItem menuItemFileNew;
    private JMenuItem menuItemFileOpen;
    private JMenuItem menuItemFileExit;
    private JMenu menuBackup;
    private JMenu menuImport;
    private JMenu menuExport;
    private JMenuItem menuItemWACImport;
    private JMenuItem menuItemShoeboxImport;
    private JMenuItem menuItemCHATImport;
    private JMenuItem menuItemTranscriberImport;
    private JMenuItem menuItemDiscoverDoc;
    private JMenuItem menuItemPublishDoc;
    private JMenu menuEdit;
    private JMenu menuSearch;
    private JMenu menuView;
    private JMenu menuOptions;
    private JCheckBoxMenuItem menuItemNativeMedia;
    private JCheckBoxMenuItem menuItemPermanentDetached;
    private JCheckBoxMenuItem menuMacNativeLF;
    private JMenu menuP2P;
    private JMenu menuHelp;
    private JMenu menuVideoStandard;
    private JMenu menuAppLanguage;
    private ButtonGroup languageBG;
    private JMenu menuChangeTimePropMode;
    private JMenuItem menuItemOptionsEnglish;
    private JMenuItem menuItemOptionsDutch;
    private ElanLayoutManager layoutManager;
    private ViewerManager2 viewerManager;
    private ElanP2P elanP2P;
    private String thisEAFPath;

    /**
     * The no arg constructor creates an empty elan frame containing a menubar
     * with a limited set of menu items.
     */
    public ElanFrame2() {
        String p2p = System.getProperty("P2P");

        if ((p2p != null) && p2p.equals("true")) {
            //			elanP2P = new ElanP2P(this);
        }

        if (allEAFPaths == null) {
            allEAFPaths = new Vector();
            allElanFrames = new Vector();
        }

        // set the initial title
        setTitle("Elan");
        frameCount++;
        initFrame();
    }

    /**
     * Constructor that accepts the path to an .eaf file. This first creates an
     * empty frame and then calls openEAF to open the specified .eaf file.
     *
     * @param path the location of the eaf file
     *
     * @see #openEAF(String)
     */
    public ElanFrame2(final String path) {
        this();

        // remember the construction of this frame for this .eaf file
        // TODO save and saveAs must also update vectors
        // TODO a FrameManager should be introduced to administer these things
        if (allEAFPaths == null) {
            allEAFPaths = new Vector();
            allElanFrames = new Vector();
        }

        thisEAFPath = new File(path).getAbsolutePath();
        allEAFPaths.insertElementAt(thisEAFPath, 0);
        allElanFrames.insertElementAt(this, 0);

        SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    openEAF(path);
                }
            });
    }

    /**
     * Creates a new ElanFrame2 instance
     *
     * @param eafPath DOCUMENT ME!
     * @param mediaFiles DOCUMENT ME!
     */
    public ElanFrame2(final String eafPath, final Vector mediaFiles) {
        this();

        // remember the construction of this frame for this .eaf file
        // TODO save and saveAs must also update vectors
        if (allEAFPaths == null) {
            allEAFPaths = new Vector();
            allElanFrames = new Vector();
        }

        thisEAFPath = new File(eafPath).getAbsolutePath();
        allEAFPaths.insertElementAt(thisEAFPath, 0);
        allElanFrames.insertElementAt(this, 0);

        SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    openEAF(eafPath, mediaFiles);
                }
            });
    }

    /**
     * Constructor that accepts a Transcription object to use for the current
     * ElanFrame.
     *
     * @param transcription the trancription
     */
    public ElanFrame2(Transcription transcription) {
        this();
        transcriptionForThisFrame = transcription;

        // fill the frame if transcription != null
        if (transcriptionForThisFrame != null) {
            try {
                // remember the construction of this frame for this transcriptions its .eaf file
                if (allEAFPaths == null) {
                    allEAFPaths = new Vector();
                    allElanFrames = new Vector();
                }

                thisEAFPath = transcription.getFullPath();

                if (thisEAFPath.startsWith("file:")) {
                    thisEAFPath = thisEAFPath.substring(5);
                }

                allEAFPaths.insertElementAt(thisEAFPath, 0);
                allElanFrames.insertElementAt(this, 0);

                //new InitThread(transcriptionForThisFrame.getName()).start();
                initElan();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void doNew() {
        Vector mediaDescriptors = new Vector();
        Vector fileNames = showMultipleFileChooser();

        if (fileNames != null) {
            //check if non-existing filenames were entered
            int fileNames_size = fileNames.size();

            for (int i = 0; i < fileNames_size; i++) {
                String strFile = (String) fileNames.elementAt(i);

                if ((new File(strFile)).exists() == false) {
                    String strMessage = ElanLocale.getString(
                            "Menu.Dialog.Message1");
                    strMessage += (new File(strFile)).getName();
                    strMessage += ElanLocale.getString("Menu.Dialog.Message2");

                    String strError = ElanLocale.getString("Message.Error");
                    JOptionPane.showMessageDialog(this, strMessage, strError,
                        JOptionPane.ERROR_MESSAGE);

                    return;
                }
            }

            //get first template file; if there are more template files, rest is not used
            String strTemplate = "";

            for (int i = fileNames_size - 1; i >= 0; i--) {
                String strFile = (String) fileNames.elementAt(i);

                if (strFile.toLowerCase().endsWith(".etf")) {
                    // use the first etf file in the list
                    strTemplate = (String) fileNames.elementAt(i);

                    // remove template files
                    fileNames.remove(i);
                }
            }

            //mediaDescriptors = createMediaDescriptors(fileNames);
            mediaDescriptors = MediaDescriptorUtil.createMediaDescriptors(fileNames);

            // create the Transcription
            try {
                Transcription nextTranscription;

                if (strTemplate.equals("")) {
                    nextTranscription = new TranscriptionImpl();
                } else {
                    nextTranscription = new TranscriptionImpl(new File(
                                strTemplate).getAbsolutePath());
                    nextTranscription.setName(TranscriptionImpl.UNDEFINED_FILE_NAME);
                }

                nextTranscription.setMediaDescriptors(mediaDescriptors);

                nextTranscription.setChanged();

                if (transcriptionForThisFrame != null) {
                    // create a new frame
                    new ElanFrame2(nextTranscription);
                } else {
                    transcriptionForThisFrame = nextTranscription;

                    //new InitThread(transcriptionForThisFrame.getName()).start();
                    initElan();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * DOCUMENT ME!
     */
    public void doOpen() {
        JFileChooser chooser = new JFileChooser();
        chooser.setFileFilter(ElanFileFilter.createFileFilter(
                ElanFileFilter.EAF_TYPE));
        chooser.setDialogTitle(ElanLocale.getString(
                "Frame.ElanFrame.OpenDialog.Title"));
        setFileChooserDir(chooser,
            (String) Preferences.get("LastUsedEAFDir", null));

        int returnVal = chooser.showOpenDialog(this);

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            Preferences.set("LastUsedEAFDir",
                (new File(chooser.getSelectedFile().getAbsolutePath())).getParent(),
                null);
            openEAF(chooser.getSelectedFile().getAbsolutePath());
        }
    }

    /**
     * Open an .eaf file defined by a full path string
     *
     * @param fullPath
     * @param mediaFiles DOCUMENT ME!
     */
    private void openEAF(String fullPath, Vector mediaFiles) {
        File fileTemp = new File(fullPath);

        //check if file exists and is a file
        if (!fileTemp.exists() || fileTemp.isDirectory()) {
            String strMessage = ElanLocale.getString("Menu.Dialog.Message1");
            strMessage += fullPath;
            strMessage += ElanLocale.getString("Menu.Dialog.Message2");

            String strError = ElanLocale.getString("Message.Error");
            JOptionPane.showMessageDialog(this, strMessage, strError,
                JOptionPane.ERROR_MESSAGE);

            return;
        }

        //check if file is a '.eaf' file
        if (fileTemp.toString().toLowerCase().endsWith(".eaf") == false) {
            String strMessage = ElanLocale.getString("Menu.Dialog.Message1");
            strMessage += fullPath;
            strMessage += ElanLocale.getString("Menu.Dialog.Message3");

            String strError = ElanLocale.getString("Message.Error");
            JOptionPane.showMessageDialog(this, strMessage, strError,
                JOptionPane.ERROR_MESSAGE);

            return;
        }

        //open the eaf and get the Transcription from it
        try {
            // When config files are possible check if eaf or configuration file
            //           String path = chooser.getSelectedFile().getAbsolutePath();
            //String path = fullPath;
            String path = fileTemp.getAbsolutePath();

            // replace all backslashes by forward slashes
            path = path.replace('\\', '/');

            //long before = System.currentTimeMillis();
            Transcription transcription = new TranscriptionImpl(new File(path).getAbsolutePath());

            //long after = System.currentTimeMillis();
            //System.out.println("open eaf took " + (after - before) + " ms");
            transcription.setUnchanged();

            if (mediaFiles != null) {
                //Vector descriptors = createMediaDescriptors(mediaFiles);
                Vector descriptors = MediaDescriptorUtil.createMediaDescriptors(mediaFiles);

                // improve this; check and compare with the medianames from the eaf
                transcription.setMediaDescriptors(descriptors);
                transcription.setChanged();
            }

            int lastSlash = path.lastIndexOf('/');
            String eafPath = path.substring(0, lastSlash);
            boolean validMedia = checkMedia(transcription, eafPath);

            if (!validMedia) {
                // ask if incomplete media session is ok, if not return
                int answer = JOptionPane.showConfirmDialog(this,
                        ElanLocale.getString(
                            "Frame.ElanFrame.IncompleteMediaQuestion"),
                        ElanLocale.getString(
                            "Frame.ElanFrame.IncompleteMediaAvailable"),
                        JOptionPane.YES_NO_OPTION);

                if (answer != JOptionPane.YES_OPTION) {
                    return;
                }
            }

            if (transcriptionForThisFrame != null) {
                // create a new ElanFrame for the Transcription
                new ElanFrame2(transcription);
            } else {
                transcriptionForThisFrame = transcription;

                //new InitThread(transcriptionForThisFrame.getName()).start();
                initElan();

                if (thisEAFPath == null) {
                    thisEAFPath = fileTemp.getAbsolutePath();
                    allEAFPaths.add(thisEAFPath);
                }

                if (!allElanFrames.contains(this)) {
                    allElanFrames.add(this);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * DOCUMENT ME!
     *
     * @param fullPath DOCUMENT ME!
     */
    public void openEAF(String fullPath) {
        openEAF(fullPath, null);
    }

    /**
     * Returns an already existing or if needed a newly created ElanFrame2 for
     * an .eaf file
     *
     * @param eafPath DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public ElanFrame2 getFrameFor(String eafPath) {
        if (!allEAFPaths.contains(eafPath)) {
            openEAF(eafPath);
        }

        int i = allEAFPaths.indexOf(eafPath);
        ElanFrame2 frame = null;

        if (i >= 0) {
            frame = (ElanFrame2) allElanFrames.elementAt(i);
        }

        return frame;
    }

    /**
     * Returns the viewermanager for this frame
     *
     * @return DOCUMENT ME!
     */
    public ViewerManager2 getViewerManager() {
        return viewerManager;
    }

    /**
     * Check for existence of media files and fix URLs if needed and possible.
     * The directory from which the .eaf file came is used as an alternative
     * location for the media file if the absolute path does not exist. When
     * the file is not found the user is prompted with a file chooser to
     * locate the file.
     *
     * @param transcription
     * @param eafPath DOCUMENT ME!
     *
     * @return boolean that flags if the media descriptors are valid
     */
    private boolean checkMedia(Transcription transcription, String eafPath) {
        boolean validMedia = true;
        File currentDirectory = null;

        try {
            Vector mediaDescriptors = transcription.getMediaDescriptors();

            for (int i = 0; i < mediaDescriptors.size(); i++) {
                MediaDescriptor md = (MediaDescriptor) mediaDescriptors.elementAt(i);

                // remove the file: part of the URL, leading slashes are no problem
                int colonPos = md.mediaURL.indexOf(':');
                String fileName = md.mediaURL.substring(colonPos + 1);

                // replace all back slashes by forward slashes
                fileName = fileName.replace('\\', '/');

                File file = new File(fileName);

                if (!file.exists()) {
                    // look for the file in the local directory
                    int lastSlashPos = fileName.lastIndexOf('/');
                    String localFileName = fileName.substring(lastSlashPos + 1);
                    file = new File(eafPath + "/" + localFileName);

                    if (file.exists()) {
                        // adjust urls
                        adjustMediaDescriptors(mediaDescriptors, i,
                            file.getAbsolutePath());
                        transcription.setChanged();

                        continue;
                    }

                    // look in a relative path ../Media
                    file = new File(eafPath + "/../Media/" + localFileName);

                    if (file.exists()) {
                        // adjust urls
                        adjustMediaDescriptors(mediaDescriptors, i,
                            file.getAbsolutePath());
                        transcription.setChanged();

                        continue;
                    }

                    // look in a relative path ../media
                    file = new File(eafPath + "/../media/" + localFileName);

                    if (file.exists()) {
                        // adjust urls
                        adjustMediaDescriptors(mediaDescriptors, i,
                            file.getAbsolutePath());
                        transcription.setChanged();

                        continue;
                    }

                    // no fallback worked, prompt the user to locate the file
                    JFileChooser chooser = new JFileChooser();

                    if (md.mimeType.equals(MediaDescriptor.WAV_MIME_TYPE)) {
                        chooser.setFileFilter(ElanFileFilter.createFileFilter(
                                ElanFileFilter.WAV_TYPE));
                    } else if (md.mimeType.equals(MediaDescriptor.MPG_MIME_TYPE)) {
                        chooser.setFileFilter(ElanFileFilter.createFileFilter(
                                ElanFileFilter.MPEG_TYPE));
                    } else {
                        chooser.setFileFilter(ElanFileFilter.createFileFilter(
                                ElanFileFilter.MEDIA_TYPE));
                    }

                    chooser.setDialogTitle(ElanLocale.getString(
                            "Frame.ElanFrame.LocateMedia"));

                    boolean found = false;

                    while (!found) {
                        if (currentDirectory != null) {
                            chooser.setCurrentDirectory(currentDirectory);
                        }

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

                        int returnVal = chooser.showOpenDialog(this);

                        if (returnVal == JFileChooser.APPROVE_OPTION) {
                            currentDirectory = chooser.getCurrentDirectory();

                            String name = chooser.getSelectedFile().getName();

                            //if (name.equals(localFileName)) {
                            if (!chooser.getSelectedFile().exists()) {
                                JOptionPane.showMessageDialog(null,
                                    ElanLocale.getString(
                                        "Frame.ElanFrame.LocateMedia"),
                                    ElanLocale.getString("Message.Error"),
                                    JOptionPane.ERROR_MESSAGE);
                                found = false;

                                continue;
                            }

                            // adjust urls
                            adjustMediaDescriptors(mediaDescriptors, i,
                                chooser.getSelectedFile().getAbsolutePath());
                            transcription.setChanged();

                            found = true;

                            /*} else {
                               // we do not allow another media file name than the original
                               JOptionPane.showMessageDialog(null,
                                   ElanLocale.getString(
                                       "Frame.ElanFrame.MediaFileRenamed"),
                                   ElanLocale.getString("Message.Error"),
                                   JOptionPane.ERROR_MESSAGE);
                               }
                             */
                        } else {
                            // the user did choose cancel and thereby gave up locating the file
                            md.isValid = false;
                            validMedia = false;

                            break;
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return validMedia;
    }

    /**
     * Replace the current path in a media descriptor and all the media
     * descriptors that are derived from it
     *
     * @param mediaDescriptors
     * @param index position in the Vector of descriptors of the descriptor
     *        which media URL must be changed
     * @param newPath the new file path that must become the new media URL
     */
    private void adjustMediaDescriptors(Vector mediaDescriptors, int index,
        String newPath) {
        // remember the old URL
        String oldURL = ((MediaDescriptor) mediaDescriptors.elementAt(index)).mediaURL;

        //String newURL = pathToURLString(newPath);
        String newURL = FileUtility.pathToURLString(newPath);
        String newExt = null;

        if (newURL.indexOf('.') > -1) {
            newExt = newURL.substring(newURL.lastIndexOf('.') + 1);
        }

        // replace the old URL and mime type
        ((MediaDescriptor) mediaDescriptors.elementAt(index)).mediaURL = newURL;
        ((MediaDescriptor) mediaDescriptors.elementAt(index)).mimeType = MediaDescriptorUtil.mimeTypeForExtension(newExt);

        // replace the extracted from URL's
        for (int i = 0; i < mediaDescriptors.size(); i++) {
            String extractedFrom = ((MediaDescriptor) mediaDescriptors.elementAt(i)).extractedFrom;

            if (oldURL.equals(extractedFrom)) {
                ((MediaDescriptor) mediaDescriptors.elementAt(i)).extractedFrom = newURL;
            }
        }
    }

    /**
     * Tries to construct a Transcription from a Shoebox .txt file, a Shoebox
     * .typ file and a media file.
     */
    private void doImportShoebox() {
        Object result = ImportShoeboxWAC.showDialog(this,
                ImportShoeboxWAC.SHOEBOX);

        if (result instanceof Hashtable) {
            String txtFileName = (String) ((Hashtable) result).get(ImportShoeboxWAC.TEXT_KEY);

            try {
                TranscriptionImpl nextTranscription = new TranscriptionImpl(txtFileName);

                // A new Shoebox transcription starts with changed = false when the shoebox file
                // contains no tiers
                nextTranscription.setChanged();

                // replace all backslashes by forward slashes
                txtFileName = txtFileName.replace('\\', '/');

                int lastSlash = txtFileName.lastIndexOf('/');
                String toolboxPath = txtFileName.substring(0, lastSlash);
                boolean validMedia = checkMedia(nextTranscription, toolboxPath);

                if (!validMedia) {
                    // ask if no media session is ok, if not return
                    int answer = JOptionPane.showConfirmDialog(this,
                            ElanLocale.getString(
                                "Frame.ElanFrame.IncompleteMediaQuestion"),
                            ElanLocale.getString(
                                "Frame.ElanFrame.IncompleteMediaAvailable"),
                            JOptionPane.YES_NO_OPTION);

                    if (answer != JOptionPane.YES_OPTION) {
                        return;
                    }
                }

                if (transcriptionForThisFrame != null) {
                    // create a new frame
                    new ElanFrame2(nextTranscription); //, true); // should be checked for valid media?
                } else {
                    transcriptionForThisFrame = nextTranscription;

                    //new InitThread(transcriptionForThisFrame.getName()).start();
                    initElan();
                }
            } catch (Exception e) {
                String message = (e.getMessage() != null) ? e.getMessage()
                                                          : e.getClass()
                                                             .getName();
                JOptionPane.showMessageDialog(this,
                    (ElanLocale.getString("ImportDialog.Message.UnknownError") +
                    "\n" + message), ElanLocale.getString("Message.Error"),
                    JOptionPane.ERROR_MESSAGE);
                e.printStackTrace();
            }
        }
    }

    /**
     * Tries to construct a Transcription from a CHAT .cha file.
     */
    private void doImportCHAT() {
        JFileChooser chooser = new JFileChooser();

        chooser.setFileFilter(ElanFileFilter.createFileFilter(
                ElanFileFilter.CHAT_TYPE));
        chooser.setDialogTitle(ElanLocale.getString(
                "Frame.ElanFrame.OpenDialog.Title"));
        setFileChooserDir(chooser,
            (String) Preferences.get("LastUsedCHATDir", null));

        int returnVal = chooser.showOpenDialog(this);

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            openCHAT(chooser.getSelectedFile().getAbsolutePath());
        }
    }

    /**
     * Open an .eaf file defined by a full path string
     *
     * @param fullPath
     */
    public void openCHAT(String fullPath) {
        File fileTemp = new File(fullPath);

        //check if file exists and is a file
        if (!fileTemp.exists() || fileTemp.isDirectory()) {
            String strMessage = ElanLocale.getString("Menu.Dialog.Message1");
            strMessage += fullPath;
            strMessage += ElanLocale.getString("Menu.Dialog.Message2");

            String strError = ElanLocale.getString("Message.Error");
            JOptionPane.showMessageDialog(this, strMessage, strError,
                JOptionPane.ERROR_MESSAGE);

            return;
        }

        //check if file is a '.cha' file
        if (fileTemp.toString().toLowerCase().endsWith(".cha") == false) {
            String strMessage = ElanLocale.getString("Menu.Dialog.Message1");
            strMessage += fullPath;
            strMessage += ElanLocale.getString("Menu.Dialog.Message3");

            String strError = ElanLocale.getString("Message.Error");
            JOptionPane.showMessageDialog(this, strMessage, strError,
                JOptionPane.ERROR_MESSAGE);

            return;
        }

        //open the cha and get the Transcription from it
        try {
            // When config files are possible check if eaf or configuration file
            //           String path = chooser.getSelectedFile().getAbsolutePath();
            String path = fullPath;
            Preferences.set("LastUsedCHATDir", (new File(path)).getParent(),
                null);

            // replace all backslashes by forward slashes
            path = path.replace('\\', '/');

            //long before = System.currentTimeMillis();
            Transcription transcription = new TranscriptionImpl(new File(path).getAbsolutePath());

            //long after = System.currentTimeMillis();
            //System.out.println("open eaf took " + (after - before) + "ms");
            transcription.setUnchanged();

            int lastSlash = path.lastIndexOf('/');
            String chatPath = path.substring(0, lastSlash);
            boolean validMedia = checkMedia(transcription, chatPath);

            if (!validMedia) {
                // ask if no media session is ok, if not return
                int answer = JOptionPane.showConfirmDialog(this,
                        ElanLocale.getString(
                            "Frame.ElanFrame.IncompleteMediaQuestion"),
                        ElanLocale.getString(
                            "Frame.ElanFrame.IncompleteMediaAvailable"),
                        JOptionPane.YES_NO_OPTION);

                if (answer != JOptionPane.YES_OPTION) {
                    return;
                }
            }

            if (transcriptionForThisFrame != null) {
                // create a new ElanFrame for the Transcription
                new ElanFrame2(transcription);
            } else {
                transcriptionForThisFrame = transcription;

                //new InitThread(transcriptionForThisFrame.getName()).start();
                initElan();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Tries to construct a Transcription from a Transcriber .trs file.
     */
    private void doImportTranscriber() {
        JFileChooser chooser = new JFileChooser();

        chooser.setFileFilter(ElanFileFilter.createFileFilter(
                ElanFileFilter.TRANSCRIBER_TYPE));
        chooser.setDialogTitle(ElanLocale.getString(
                "Frame.ElanFrame.OpenDialog.Title"));
        setFileChooserDir(chooser,
            (String) Preferences.get("LastUsedTranscriberDir", null));

        int returnVal = chooser.showOpenDialog(this);

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            openTranscriber(chooser.getSelectedFile().getAbsolutePath());
        }
    }

    /**
     * Open a .trs file defined by a full path string
     *
     * @param fullPath
     */
    public void openTranscriber(String fullPath) {
        File fileTemp = new File(fullPath);

        //check if file exists and is a file
        if (!fileTemp.exists() || fileTemp.isDirectory()) {
            String strMessage = ElanLocale.getString("Menu.Dialog.Message1");
            strMessage += fullPath;
            strMessage += ElanLocale.getString("Menu.Dialog.Message2");

            String strError = ElanLocale.getString("Message.Error");
            JOptionPane.showMessageDialog(this, strMessage, strError,
                JOptionPane.ERROR_MESSAGE);

            return;
        }

        //check if file is a '.trs' file
        if (fileTemp.toString().toLowerCase().endsWith(".trs") == false) {
            String strMessage = ElanLocale.getString("Menu.Dialog.Message1");
            strMessage += fullPath;
            strMessage += ElanLocale.getString("Menu.Dialog.Message3");

            String strError = ElanLocale.getString("Message.Error");
            JOptionPane.showMessageDialog(this, strMessage, strError,
                JOptionPane.ERROR_MESSAGE);

            return;
        }

        //open the trs and get the Transcription from it
        try {
            String path = fullPath;
            Preferences.set("LastUsedTranscriberDir",
                (new File(path)).getParent(), null);

            // replace all backslashes by forward slashes
            path = path.replace('\\', '/');

            //long before = System.currentTimeMillis();
            Transcription transcription = new TranscriptionImpl(new File(path).getAbsolutePath());

            //long after = System.currentTimeMillis();
            //System.out.println("open eaf took " + (after - before) + "ms");
            transcription.setUnchanged();

            int lastSlash = path.lastIndexOf('/');
            String transcriberPath = path.substring(0, lastSlash);
            boolean validMedia = checkMedia(transcription, transcriberPath);

            if (!validMedia) {
                // ask if no media session is ok, if not return
                int answer = JOptionPane.showConfirmDialog(this,
                        ElanLocale.getString(
                            "Frame.ElanFrame.IncompleteMediaQuestion"),
                        ElanLocale.getString(
                            "Frame.ElanFrame.IncompleteMediaAvailable"),
                        JOptionPane.YES_NO_OPTION);

                if (answer != JOptionPane.YES_OPTION) {
                    return;
                }
            }

            if (transcriptionForThisFrame != null) {
                // create a new ElanFrame for the Transcription
                new ElanFrame2(transcription);
            } else {
                transcriptionForThisFrame = transcription;

                //new InitThread(transcriptionForThisFrame.getName()).start();
                initElan();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Tries to construct a Transcription from a WAC .wac.txt file, a Shoebox
     * .typ file and a media file.
     */

    /*    private void doImportWAC() {
       Object result = ImportShoeboxWAC.showDialog(this, ImportShoeboxWAC.WAC);
       if (result instanceof Hashtable) {
           String txtFileName = (String) ((Hashtable) result).get(ImportShoeboxWAC.TEXT_KEY);
           String typFileName = (String) ((Hashtable) result).get(ImportShoeboxWAC.TYPE_KEY);
           //String mediaFileName = (String)((Hashtable)result).get(ImportShoeboxWAC.MEDIA_KEY);
           Vector mediaFileNames = (Vector) ((Hashtable) result).get(ImportShoeboxWAC.MEDIA_KEY);
           try {
               File wacFile = new File(txtFileName); //should be ok...
               ShoeboxTranscription nextTranscription = new ShoeboxTranscription(wacFile,
                       typFileName, (String) mediaFileNames.get(0));
               nextTranscription.setChanged();
               //nextTranscription.setMediaDescriptors(createMediaDescriptors(
               //        mediaFileNames));
               nextTranscription.setMediaDescriptors(
                   MediaDescriptorUtil.createMediaDescriptors(mediaFileNames));
               if (transcriptionForThisFrame != null) {
                   // create a new frame
                   new ElanFrame2(nextTranscription); //, true);  // should be checked for valid media?
               } else {
                   transcriptionForThisFrame = nextTranscription;
                   //new InitThread(nextTranscription.getName()).start();
                   initElan();
               }
           } catch (Exception e) {
               JOptionPane.showMessageDialog(this,
                   ElanLocale.getString("ImportDialog.Message.UnknownError"),
                   ElanLocale.getString("Message.Error"),
                   JOptionPane.ERROR_MESSAGE);
           }
       }
       } */

    /**
     * Init Elan for a Transcription mediaDecriptors should be contained in
     * Transcription Is this the place to create all the viewers, must there
     * be getters for these viewers who needs to know about them?
     */
    private void initElan() {
        setTitle("Initializing....");

        viewerManager = new ViewerManager2(transcriptionForThisFrame);
        layoutManager = new ElanLayoutManager(this, viewerManager);
        ELANCommandFactory.addDocument(this, viewerManager, layoutManager);
        MediaDescriptorUtil.createMediaPlayers((TranscriptionImpl) transcriptionForThisFrame,
            transcriptionForThisFrame.getMediaDescriptors());

        ElanMediaPlayerController mediaController = viewerManager.getMediaPlayerController();
        layoutManager.add(mediaController);

        TimeLineViewer timeLineViewer = viewerManager.createTimeLineViewer();
        layoutManager.add(timeLineViewer);

        InterlinearViewer interlinearViewer = viewerManager.createInterlinearViewer();
        layoutManager.add(interlinearViewer);

        layoutManager.showTimeLineViewer();

        GridViewer gridViewer = viewerManager.createGridViewer();
        layoutManager.add(gridViewer);

        TextViewer textViewer = viewerManager.createTextViewer();
        layoutManager.add(textViewer);

        SubtitleViewer subtitleViewer1 = viewerManager.createSubtitleViewer();
        layoutManager.add(subtitleViewer1);

        SubtitleViewer subtitleViewer2 = viewerManager.createSubtitleViewer();
        layoutManager.add(subtitleViewer2);

        SubtitleViewer subtitleViewer3 = viewerManager.createSubtitleViewer();
        layoutManager.add(subtitleViewer3);

        SubtitleViewer subtitleViewer4 = viewerManager.createSubtitleViewer();
        layoutManager.add(subtitleViewer4);

        LinkedFileDescriptorUtil.initLinkedFiles((TranscriptionImpl) transcriptionForThisFrame);

        //		layoutManager.add(new mpi.eudico.p2p.CollaborationPanel());
        if (elanP2P != null) {
            elanP2P.setManagers(viewerManager, layoutManager);
        }

        // temp block for svg
        if (SVGPrefs.getUseSVG() ||
                (((TranscriptionImpl) transcriptionForThisFrame).getSVGFile() != null)) {
            // lightweight svgviewer

            /*
               GlassPaneSVGViewer svgViewer = viewerManager.createSVGViewer();
               svgViewer.setUnderlyingComponent(viewerManager.getMasterMediaPlayer().getVisualComponent());
               this.getLayeredPane().setLayout(null);
               this.getLayeredPane().add(svgViewer, JLayeredPane.DEFAULT_LAYER);
             */
            if (viewerManager.getMasterMediaPlayer() instanceof JMFGraphicMediaPlayer) {
                // don't need to add to layout
                menuItemFileOpen.setEnabled(false);
                menuItemFileNew.setEnabled(false);
                menuImport.setEnabled(false);
            }
        }

        ElanLocale.addElanLocaleListener(transcriptionForThisFrame, this);

        setFrameTitle();

        initMenusAndCommands();

        loadPreferences();

        // instantiate Viewer components:
        //  use CommandActions for relevant toolbar buttons and combobox menu items
        //  position and size components using LayoutManager
        layoutManager.doLayout();

        //  this sucks but is needed to ensure visible video on the mac
        viewerManager.getMasterMediaPlayer().setMediaTime(0);
    }

    private void setFrameTitle() {
        try {
            if (transcriptionForThisFrame != null) {
                if (transcriptionForThisFrame.getName().equals(TranscriptionImpl.UNDEFINED_FILE_NAME)) {
                    setTitle("Elan - " +
                        ElanLocale.getString(
                            "Frame.ElanFrame.UndefinedFileName"));
                } else {
                    setTitle("Elan - " + transcriptionForThisFrame.getName());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Performs some general initialization for an empty frame.
     */
    private void initFrame() {
        // create the initial menu items
        initMenuBar();

        // listen for WindowEvents events on the ElanFrame
        addWindowListener(new ElanFrameWindowListener());

        // require the program to handle the operation in the
        // windowClosing method of a registered WindowListener object.
        setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

        // add this elanframe to locale listener
        //ElanLocale.addElanLocaleListener(this);
        pack();

        /*
           Dimension dimSize = new Dimension(800, 650);
           setSize((int)dimSize.getWidth(), (int)dimSize.getHeight());
           Dimension dimLocation = Toolkit.getDefaultToolkit().getScreenSize();
           setLocation((int)(dimLocation.getWidth()/2-getWidth()/2),(int)(dimLocation.getHeight()/2-getHeight()/2));
         */
        Dimension d = (Dimension) Preferences.get("FrameSize", null);

        if (d != null) {
            setSize(d);
        } else {
            Dimension dimSize = new Dimension(800, 650);
            setSize((int) dimSize.getWidth(), (int) dimSize.getHeight());
        }

        Point p = (Point) Preferences.get("FrameLocation", null);

        if (p != null) {
            setLocation(p);
        } else {
            Dimension dimLocation = Toolkit.getDefaultToolkit().getScreenSize();
            setLocation((int) ((dimLocation.getWidth() / 2) - (getWidth() / 2)),
                (int) ((dimLocation.getHeight() / 2) - (getHeight() / 2)));
        }

        setVisible(true);
    }

    private void initMenuBar() {
        menuBar = new JMenuBar();

        setJMenuBar(menuBar);

        //make menu visible / appear above heavyweight video
        JPopupMenu.setDefaultLightWeightPopupEnabled(false);

        menuFile = new JMenu();
        menuBar.add(menuFile);

        menuItemFileNew = new JMenuItem();
        menuItemFileNew.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
                Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
        menuItemFileNew.addActionListener(this);
        menuItemFileNew.setActionCommand("MENUFILENEW");
        menuFile.add(menuItemFileNew);

        menuItemFileOpen = new JMenuItem();
        menuItemFileOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,
                Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
        menuItemFileOpen.addActionListener(this);
        menuItemFileOpen.setActionCommand("MENUFILEOPEN");
        menuFile.add(menuItemFileOpen);

        menuFile.addSeparator();

        menuImport = new JMenu();
        menuFile.add(menuImport);

        menuItemShoeboxImport = new JMenuItem();
        menuItemShoeboxImport.addActionListener(this);
        menuItemShoeboxImport.setActionCommand("ImportShoebox");
        menuImport.add(menuItemShoeboxImport);

        menuItemCHATImport = new JMenuItem();
        menuItemCHATImport.addActionListener(this);
        menuItemCHATImport.setActionCommand("ImportCHAT");
        menuImport.add(menuItemCHATImport);

        menuItemTranscriberImport = new JMenuItem();
        menuItemTranscriberImport.addActionListener(this);
        menuItemTranscriberImport.setActionCommand("ImportTranscriber");
        menuImport.add(menuItemTranscriberImport);

        //	menuItemWACImport = new JMenuItem();
        //	menuItemWACImport.addActionListener(this);
        //	menuItemWACImport.setActionCommand("ImportWAC");
        //	menuImport.add(menuItemWACImport);
        menuFile.addSeparator();

        menuItemFileExit = new JMenuItem();
        menuItemFileExit.addActionListener(this);
        menuItemFileExit.setActionCommand("MENUFILEEXIT");
        menuFile.add(menuItemFileExit);

        menuEdit = new JMenu();
        menuBar.add(menuEdit); // should be added as second, although initially invisible
        menuEdit.setVisible(false); // initially don't show

        menuView = new JMenu();
        menuBar.add(menuView);
        menuView.setVisible(false);

        menuOptions = new JMenu();
        menuBar.add(menuOptions);

        // temporary and therefore old fashioned menu item to allow fallback to JMF media players
        // on windows machines. As soon as native media is succesfully used in a few releases
        // this menu item can be deleted. The only action performed while toggling this item is
        // setting the PreferredMediaFramework property that is used by the player factory
        if (System.getProperty("os.name").toLowerCase().indexOf("windows") > -1) {
            menuItemNativeMedia = new JCheckBoxMenuItem();
            menuItemNativeMedia.setText("Use Native Media Platform");
            menuItemNativeMedia.addActionListener(this);

            // haal de state uit de property
            boolean nativePrefered = true;
            String preferredMF = System.getProperty("PreferredMediaFramework");

            // set here default choice if nothing defined
            if (preferredMF == null) {
                System.setProperty("PreferredMediaFramework", "NativeWindows");

                //System.setProperty("PreferredMediaFramework", "JMF");
            } else if (!preferredMF.equals("NativeWindows")) {
                nativePrefered = false;
            }

            menuItemNativeMedia.setState(nativePrefered);

            // optionally suppress jmf support for the standalone version
            String suppressJMF = System.getProperty("suppressJMF");

            if ((suppressJMF == null) ||
                    !suppressJMF.toLowerCase().equals("true")) {
                menuOptions.add(menuItemNativeMedia);
            }

            //menuOptions.add(menuItemNativeMedia);
        }

        if (elanP2P != null) {
            menuP2P = new JMenu();
            menuBar.add(menuP2P);
            menuItemDiscoverDoc = new JMenuItem();
            menuItemDiscoverDoc.addActionListener(this);
            menuItemDiscoverDoc.setActionCommand("DiscoverDoc");
            menuP2P.add(menuItemDiscoverDoc);
        }

        if (System.getProperty("os.name").startsWith("Mac OS")) {
            // inserted by AR to allow choice for permanent detached video at startup
            menuItemPermanentDetached = new JCheckBoxMenuItem();
            menuItemPermanentDetached.setText("Use detached media window");
            menuItemPermanentDetached.addActionListener(this);

            // haal de state uit de preferences
            Boolean permanentDetached = (Boolean) Preferences.get("PreferredMediaWindow",
                    null);

            if (permanentDetached == null) {
                permanentDetached = new Boolean(false); // default usage is attached media window
            }

            menuItemPermanentDetached.setState(permanentDetached.booleanValue());
            menuOptions.add(menuItemPermanentDetached);

            // end of insertion by AR
            // Mac L&F
            menuMacNativeLF = new JCheckBoxMenuItem();
            menuMacNativeLF.setText("Use Mac Look And Feel");
            menuMacNativeLF.setActionCommand("MacNativeLF");
            menuMacNativeLF.addActionListener(this);

            Boolean macNativePref = (Boolean) Preferences.get("UseMacLF", null);
            menuOptions.add(menuMacNativeLF);

            if ((macNativePref != null) && !macNativePref.booleanValue()) {
                menuMacNativeLF.setState(false);

                try {
                    UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
                    SwingUtilities.updateComponentTreeUI(this);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                menuMacNativeLF.setState(true);
            }

            // use reflection to make this compile on all systems
            try {
                Class macHandler = Class.forName(
                        "mpi.eudico.client.mac.MacAppHandler");
                Class macList = Class.forName(
                        "mpi.eudico.client.mac.MacApplicationListener");
                java.lang.reflect.Constructor con = macHandler.getConstructor(new Class[] {
                            macList
                        });
                con.newInstance(new Object[] { this });
            } catch (Exception ex) {
                System.out.println("Could not load Mac application handler.");
            }
        }

        updateLocale();
    }

    /**
     * DOCUMENT ME!
     *
     * @param e DOCUMENT ME!
     */
    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();

        if (command.equals("MENUFILENEW")) {
            doNew();
        } else if (command.equals("MENUFILEOPEN")) {
            doOpen();
        } else if (command.equals("MENUFILEEXIT")) {
            doExit();
        } else if (command.equals("ImportShoebox")) {
            doImportShoebox();
        } else if (command.equals("ImportCHAT")) {
            doImportCHAT();
        } else if (command.equals("ImportTranscriber")) {
            doImportTranscriber();
        } else if (command.equals("ImportWAC")) {
            //		doImportWAC();
        } else if (command.equals("DiscoverDoc")) {
            if (elanP2P != null) {
                Command c = ELANCommandFactory.createCommand(null,
                        ELANCommandFactory.DISCOVER_DOC);
                c.execute(elanP2P, new Object[] { this });
            }
        } else if (command.equals("PublishDoc")) {
            if (elanP2P != null) {
                Command c = ELANCommandFactory.createCommand(null,
                        ELANCommandFactory.PUBLISH_DOC);
                c.execute(elanP2P,
                    new Object[] { this, transcriptionForThisFrame });
            }
        } else if (command.equals("Use Native Media Platform")) {
            boolean useNativeMedia = menuItemNativeMedia.getState();

            if (useNativeMedia) {
                System.out.println(
                    "Setting preferred media framework to Native");
                System.setProperty("PreferredMediaFramework", "NativeWindows");
            } else {
                System.out.println("Setting preferred media framework to JMF");
                System.setProperty("PreferredMediaFramework", "JMF");
            }
        } else if (command.equals("Use detached media window")) {
            Preferences.set("PreferredMediaWindow",
                new Boolean(menuItemPermanentDetached.getState()), null);
        } else if (command.equals("MacNativeLF")) {
            switchMacLF();
        }

        // HB: next cases only for locally handled commands
        // typically these need arguments from a local context
    }

    /**
     * Set an initial file path for a file chooser. If the path is null the
     * user dir is used
     *
     * @param chooser the file chooser for which the initial path must be set
     * @param dirPath String with the directory path
     */
    private void setFileChooserDir(JFileChooser chooser, String dirPath) {
        if (dirPath == null) {
            // user.dir is probably a better choice than home.dir?
            dirPath = System.getProperty("user.dir");
        }

        chooser.setCurrentDirectory(new File(dirPath));
    }

    /**
     * Presents a multiple file chooser to the user and returns the set of
     * files the user has selected. The files should be media files with
     * optionally a template file.
     *
     * @return a Vector with file paths
     */
    private Vector showMultipleFileChooser() {
        Vector vecFiles = null;
        MultiFileChooser chooser = new MultiFileChooser(MultiFileChooser.MEDIA_TEMPLATE);
        chooser.setDialogTitle(ElanLocale.getString(
                "Frame.ElanFrame.NewDialog.Title"));

        int option = chooser.showDialog(this, null);

        if (option == JFileChooser.APPROVE_OPTION) {
            Object[] files = chooser.getFiles();

            if (files.length > 0) {
                vecFiles = new Vector();

                for (int i = 0; i < files.length; i++) {
                    if (vecFiles.contains(files[i]) == false) {
                        vecFiles.add("" + files[i]);
                    }
                }
            }
        }

        return vecFiles;
    }

    private void initMenusAndCommands() {
        // instantiate CommandActions, also UndoCA and RedoCA

        /* sample:
           CommandAction playSelectionCA = ELANCommandFactory.getCommandAction(ELANCommandFactory.PLAY_SELECTION);
         */

        // instantiate JMenuItems, where possible with CommandActions as args for constructor

        /* sample:
           playSelectionItem = new JMenuItem(playSelectionCA);
           playSelectionItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
           menuInvisible.add(playSelectionItem);   // add to menu, if only for button then to invisible menu
         */

        // add actions with accelerator keys and without a menu item to the input
        // and action map
        InputMap inputMap = menuBar.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        ActionMap actionMap = menuBar.getActionMap();

        if (inputMap instanceof ComponentInputMap && (actionMap != null)) {
            Action[] invActions = new Action[] {
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.PLAY_PAUSE),
                    

                    //ELANCommandFactory.getCommandAction(transcriptionForThisFrame, ELANCommandFactory.NEW_ANNOTATION),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.GO_TO_BEGIN),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.GO_TO_END),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.SECOND_LEFT),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.SECOND_RIGHT),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.PLAY_SELECTION),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.PLAY_AROUND_SELECTION),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.PREVIOUS_ANNOTATION),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.NEXT_ANNOTATION),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.ANNOTATION_UP),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.ANNOTATION_DOWN),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.PREVIOUS_SCROLLVIEW),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.NEXT_SCROLLVIEW),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.PREVIOUS_FRAME),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.NEXT_FRAME),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.PIXEL_LEFT),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.PIXEL_RIGHT),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.CLEAR_SELECTION),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.SELECTION_BOUNDARY),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.SELECTION_MODE),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.LOOP_MODE),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.MODIFY_ANNOTATION_TIME),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.PLAYBACK_RATE_TOGGLE),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.PLAYBACK_VOLUME_TOGGLE),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.NEXT_ACTIVE_TIER),
                    ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                        ELANCommandFactory.PREVIOUS_ACTIVE_TIER)
                };

            for (int i = 0; i < invActions.length; i++) {
                inputMap.put((KeyStroke) invActions[i].getValue(
                        Action.ACCELERATOR_KEY),
                    invActions[i].getValue(Action.DEFAULT));
                actionMap.put(invActions[i].getValue(Action.DEFAULT),
                    invActions[i]);
            }
        }

        menuFile.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.SAVE)), 3);
        menuFile.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.SAVE_AS)), 4);
        menuFile.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.SAVE_AS_TEMPLATE)), 5);
        menuFile.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.SAVE_SELECTION_AS_EAF)), 6);
        menuFile.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.MERGE_TRANSCRIPTIONS)), 7);
        menuBackup = new JMenu();
        menuFile.add(menuBackup, 8);

        ButtonGroup backupGroup = new ButtonGroup();

        // retrieve the stored value for backup interval
        Integer buDelay = (Integer) Preferences.get("BackUpDelay", null);
        JRadioButtonMenuItem neverMI = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.BACKUP_NEVER));

        if ((buDelay == null) ||
                ((buDelay != null) &&
                (buDelay.compareTo(Constants.BACKUP_NEVER) == 0))) {
            neverMI.setSelected(true);
        }

        JRadioButtonMenuItem backup5MI = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.BACKUP_5));

        if ((buDelay != null) && (buDelay.compareTo(Constants.BACKUP_5) == 0)) {
            backup5MI.setSelected(true);
        }

        JRadioButtonMenuItem backup10MI = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.BACKUP_10));

        if ((buDelay != null) && (buDelay.compareTo(Constants.BACKUP_10) == 0)) {
            backup10MI.setSelected(true);
        }

        JRadioButtonMenuItem backup20MI = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.BACKUP_20));

        if ((buDelay != null) && (buDelay.compareTo(Constants.BACKUP_20) == 0)) {
            backup20MI.setSelected(true);
        }

        JRadioButtonMenuItem backup30MI = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.BACKUP_30));

        if ((buDelay != null) && (buDelay.compareTo(Constants.BACKUP_30) == 0)) {
            backup30MI.setSelected(true);
        }

        backupGroup.add(neverMI);
        backupGroup.add(backup5MI);
        backupGroup.add(backup10MI);
        backupGroup.add(backup20MI);
        backupGroup.add(backup30MI);
        menuBackup.add(neverMI);
        menuBackup.add(backup5MI);
        menuBackup.add(backup10MI);
        menuBackup.add(backup20MI);
        menuBackup.add(backup30MI);

        menuFile.insertSeparator(9);

        menuFile.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.PAGESETUP)),
            10);

        menuFile.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.PREVIEW)), 11);

        menuFile.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.PRINT)), 12);

        menuFile.insertSeparator(13);

        menuExport = new JMenu();
        menuFile.add(menuExport, 14);

        menuExport.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.EXPORT_SHOEBOX)));

        menuExport.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.EXPORT_CHAT)));

        menuExport.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.EXPORT_TAB)));

        menuExport.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.EXPORT_INTERLINEAR)));

        menuExport.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.EXPORT_TRAD_TRANSCRIPT)));

        menuExport.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.EXPORT_SMIL)));

        menuExport.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.EXPORT_QT_SUB)));

        //		menuExport.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
        //				 transcriptionForThisFrame, ELANCommandFactory.EXPORT_TEX)));
        // maybe test here if available and only show menu item if available:
        //
        //ExportMediaCA ca = (ExportMediaCA) ELANCommandFactory.getCommandAction(transcriptionForThisFrame, ELANCommandFactory.EXPORT_MEDIA);
        //if (ca.isAvailable()) {
        menuExport.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.EXPORT_MEDIA)));

        //}
        menuExport.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.EXPORT_IMAGE_FROM_WINDOW)));

        // enable menu's
        menuEdit.setVisible(true);

        // menu items with command actions
        CommandAction undoCA = ELANCommandFactory.getUndoCA(transcriptionForThisFrame);
        ElanMenuItem undoItem = new ElanMenuItem(undoCA);

        menuEdit.add(undoItem);

        CommandAction redoCA = ELANCommandFactory.getRedoCA(transcriptionForThisFrame);
        ElanMenuItem redoItem = new ElanMenuItem(redoCA);

        menuEdit.add(redoItem);
        menuEdit.addSeparator();

        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.NEW_ANNOTATION)));
        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.NEW_ANNOTATION_BEFORE)));
        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.NEW_ANNOTATION_AFTER)));
        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.MODIFY_ANNOTATION)));
        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.DELETE_ANNOTATION)));

        if (SVGPrefs.getUseSVG() ||
                (((TranscriptionImpl) transcriptionForThisFrame).getSVGFile() != null)) {
            menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                        transcriptionForThisFrame,
                        ELANCommandFactory.MODIFY_GRAPHIC_ANNOTATION)));
        }

        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.SHIFT_ALL_DLG)));

        menuEdit.addSeparator();
        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.TOKENIZE_DLG)));

        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.FILTER_TIER_DLG)));

        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.COPY_TIER_DLG)));

        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.SEGMENTATION_DLG)));
        menuEdit.addSeparator();
        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.ADD_TIER_DLG)));
        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.CHANGE_TIER_DLG)));
        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.REPARENT_TIER_DLG)));
        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.DELETE_TIER_DLG)));

        menuEdit.addSeparator();
        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.ADD_TYPE_DLG)));
        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.CHANGE_TYPE_DLG)));
        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.DELETE_TYPE_DLG)));

        menuEdit.addSeparator();
        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.EDIT_CV_DLG)));

        menuEdit.addSeparator();
        menuEdit.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.LINKED_FILES_DLG)));

        /*
        final mpi.eudico.client.annotator.tier.Test t = new mpi.eudico.client.annotator.tier.Test(transcriptionForThisFrame);
        menuEdit.add(new javax.swing.AbstractAction("Reparent Tier..."){
            public void actionPerformed(java.awt.event.ActionEvent ae) {
                t.test();
            }
        });
        */
        menuSearch = new JMenu();
        menuBar.add(menuSearch, 2);
        menuSearch.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.SEARCH_DLG)));

        menuSearch.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.SEARCH_MULTIPLE_DLG)));

        //menuSearch.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
        //			transcriptionForThisFrame,
        //			ELANCommandFactory.STRUCTURED_SEARCH_MULTIPLE_DLG)));
        menuSearch.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.GOTO_DLG)));

        menuView.setVisible(true);

        ElanMenuItem menuItemViewTierDependencies = new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.TIER_DEPENDENCIES));
        menuView.add(menuItemViewTierDependencies);
        menuView.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.SHORTCUTS)));

        CommandAction syntaxViewerAction = ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                ELANCommandFactory.SYNTAX_VIEWER);

        if (syntaxViewerAction != null) {
            menuView.add(new ElanMenuItem(syntaxViewerAction));
        }

        // Options menu, moved to initMenuBar
        //menuOptions = new JMenu();
        //menuBar.add(menuOptions);
        menuOptions.removeAll();
        menuChangeTimePropMode = new JMenu();

        ButtonGroup timePropGroup = new ButtonGroup();
        JRadioButtonMenuItem normalModeMI = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.TIMEPROP_NORMAL));
        JRadioButtonMenuItem bulldozerModeMI = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.BULLDOZER_MODE));
        JRadioButtonMenuItem shiftModeMI = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.SHIFT_MODE));
        timePropGroup.add(normalModeMI);
        normalModeMI.setSelected(true);
        timePropGroup.add(bulldozerModeMI);
        timePropGroup.add(shiftModeMI);
        menuChangeTimePropMode.add(normalModeMI);
        menuChangeTimePropMode.add(bulldozerModeMI);
        menuChangeTimePropMode.add(shiftModeMI);
        menuOptions.add(menuChangeTimePropMode);
        menuOptions.addSeparator();

        ButtonGroup modeGroup = new ButtonGroup();
        JRadioButtonMenuItem annotationModeMI = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.ANNOTATION_MODE));
        annotationModeMI.setSelected(true);

        JRadioButtonMenuItem syncMI = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.SYNC_MODE));
        modeGroup.add(annotationModeMI);
        modeGroup.add(syncMI);
        menuOptions.add(annotationModeMI);
        menuOptions.add(syncMI);
        menuOptions.addSeparator();

        menuOptions.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.PLAY_AROUND_SELECTION_DLG)));
        menuOptions.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame,
                    ELANCommandFactory.PLAYBACK_TOGGLE_DLG)));

        menuOptions.addSeparator();

        menuVideoStandard = new JMenu();

        ButtonGroup videoGroup = new ButtonGroup();
        JRadioButtonMenuItem palMI = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.SET_PAL));
        JRadioButtonMenuItem ntscMI = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.SET_NTSC));
        videoGroup.add(palMI);
        palMI.setSelected(true);
        videoGroup.add(ntscMI);
        menuVideoStandard.add(palMI);
        menuVideoStandard.add(ntscMI);
        menuOptions.add(menuVideoStandard);
        menuOptions.addSeparator();

        menuAppLanguage = new JMenu();
        menuOptions.add(menuAppLanguage);

        languageBG = new ButtonGroup();

        JMenuItem miCatalan = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.CATALAN));
        languageBG.add(miCatalan);
        menuAppLanguage.add(miCatalan);

        JMenuItem miGerman = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.GERMAN));
        languageBG.add(miGerman);
        menuAppLanguage.add(miGerman);

        menuItemOptionsEnglish = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.ENGLISH));
        menuItemOptionsEnglish.setSelected(true);
        languageBG.add(menuItemOptionsEnglish);
        menuAppLanguage.add(menuItemOptionsEnglish);

        JMenuItem miSpanish = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.SPANISH));
        languageBG.add(miSpanish);
        menuAppLanguage.add(miSpanish);

        JMenuItem miFrench = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.FRENCH));
        languageBG.add(miFrench);
        menuAppLanguage.add(miFrench);

        menuItemOptionsDutch = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.DUTCH));
        languageBG.add(menuItemOptionsDutch);
        menuAppLanguage.add(menuItemOptionsDutch);

        JMenuItem miPortu = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.PORTUGUESE));
        languageBG.add(miPortu);
        menuAppLanguage.add(miPortu);

        JMenuItem miSwedish = new JRadioButtonMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.SWEDISH));
        languageBG.add(miSwedish);
        menuAppLanguage.add(miSwedish);

        /*
           if (menuMacNativeLF != null) {
               menuOptions.addSeparator();
               menuOptions.add(menuMacNativeLF);
           }
         */

        //		String p2p = System.getProperty("P2P");
        //		if ((p2p != null) && (System.getProperty("P2P").equals("true"))) {
        if (elanP2P != null) {
            menuItemPublishDoc = new JMenuItem();
            menuItemPublishDoc.addActionListener(this);
            menuItemPublishDoc.setActionCommand("PublishDoc");
            menuP2P.add(menuItemPublishDoc);

            //menuP2P.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(transcriptionForThisFrame, ELANCommandFactory.PUBLISH_DOC)), 0);
        }

        menuHelp = new JMenu();
        menuBar.add(menuHelp);
        menuHelp.add(new ElanMenuItem(ELANCommandFactory.getCommandAction(
                    transcriptionForThisFrame, ELANCommandFactory.ABOUT_DLG)));

        updateLocale();
    }

    /**
     * DOCUMENT ME!
     */
    public void updateLocale() {
        setFrameTitle();

        // update the language menu items
        if (languageBG != null) {
            if (languageBG.getButtonCount() > 0) {
                Enumeration en = languageBG.getElements();
                Object item;
                JRadioButtonMenuItem rbItem;

                while (en.hasMoreElements()) {
                    item = en.nextElement();

                    if (item instanceof JRadioButtonMenuItem) {
                        rbItem = (JRadioButtonMenuItem) item;

                        if (ELANCommandFactory.getLocaleForKey(
                                    rbItem.getAction().getValue(Action.DEFAULT))
                                                  .equals(ElanLocale.getLocale())) {
                            rbItem.setSelected(true);

                            break;
                        }
                    }
                }
            }
        }

        menuFile.setText(ElanLocale.getString("Menu.File"));
        menuItemFileNew.setText(ElanLocale.getString("Menu.File.New"));
        menuItemFileOpen.setText(ElanLocale.getString("Menu.File.Open"));
        menuItemFileExit.setText(ElanLocale.getString("Menu.File.Exit"));
        menuImport.setText(ElanLocale.getString("Menu.File.Import"));
        menuImport.setMnemonic((new Integer(ElanLocale.getString(
                    "MNEMONIC.File.Import"))).intValue());
        menuItemShoeboxImport.setText(ElanLocale.getString(
                "Menu.File.Import.Shoebox"));
        menuItemShoeboxImport.setMnemonic((new Integer(ElanLocale.getString(
                    "MNEMONIC.File.Import.Shoebox"))).intValue());
        menuItemCHATImport.setText(ElanLocale.getString("Menu.File.Import.CHAT"));
        menuItemTranscriberImport.setText(ElanLocale.getString(
                "Menu.File.Import.Transcriber"));

        //		menuItemCHATImport.setMnemonic((new Integer(ElanLocale.getString(
        //					"MNEMONIC.File.Import.CHAT"))).intValue());
        //		menuItemWACImport.setText(ElanLocale.getString("Menu.File.Import.WAC"));
        //		menuItemWACImport.setMnemonic((new Integer(ElanLocale.getString(
        //					"MNEMONIC.File.Import.WAC"))).intValue());
        if (menuBackup != null) {
            menuBackup.setText(ElanLocale.getString("Menu.File.Backup.Auto"));
            menuBackup.setMnemonic((new Integer(ElanLocale.getString(
                        "MNEMONIC.Menu.File.Backup.Auto"))).intValue());
        }

        if (menuExport != null) {
            menuExport.setText(ElanLocale.getString("Menu.File.Export"));
            menuExport.setMnemonic((new Integer(ElanLocale.getString(
                        "MNEMONIC.File.Export"))).intValue());
        }

        if (menuEdit != null) {
            menuEdit.setText(ElanLocale.getString("Menu.Edit"));
            menuEdit.setMnemonic((new Integer(ElanLocale.getString(
                        "MNEMONIC.Menu.Edit"))).intValue());
        }

        if (menuView != null) {
            menuView.setText(ElanLocale.getString("Menu.View"));
            menuView.setMnemonic((new Integer(ElanLocale.getString(
                        "MNEMONIC.Menu.View"))).intValue());
        }

        if (menuHelp != null) {
            menuHelp.setText(ElanLocale.getString("Menu.Help"));
            menuHelp.setMnemonic((new Integer(ElanLocale.getString(
                        "MNEMONIC.Menu.Help"))).intValue());
        }

        if (menuSearch != null) {
            menuSearch.setText(ElanLocale.getString("Menu.Search"));
            menuSearch.setMnemonic((new Integer(ElanLocale.getString(
                        "MNEMONIC.Menu.Search"))).intValue());
        }

        if (menuP2P != null) {
            menuP2P.setText(ElanLocale.getString("Menu.P2P"));
            menuItemDiscoverDoc.setText(ElanLocale.getString(
                    "Menu.P2P.DiscoverDocument"));

            if (menuItemPublishDoc != null) {
                menuItemPublishDoc.setText(ElanLocale.getString(
                        "Menu.P2P.PublishDocument"));
            }
        }

        if (menuOptions != null) {
            menuOptions.setText(ElanLocale.getString("Menu.Options"));
            menuOptions.setMnemonic((new Integer(ElanLocale.getString(
                        "MNEMONIC.Menu.Options"))).intValue());
        }

        if (menuChangeTimePropMode != null) {
            menuChangeTimePropMode.setText(ElanLocale.getString(
                    "Menu.Options.TimeChangePropagationMode"));
        }

        if (menuVideoStandard != null) {
            menuVideoStandard.setText(ElanLocale.getString(
                    "Menu.Options.VideoStandard"));
            menuVideoStandard.setMnemonic((new Integer(ElanLocale.getString(
                        "MNEMONIC.Menu.VideoStandard"))).intValue());
        }

        if (menuAppLanguage != null) {
            menuAppLanguage.setText(ElanLocale.getString(
                    "CommandActions.Language"));
            menuAppLanguage.setMnemonic((new Integer(ElanLocale.getString(
                        "MNEMONIC.Menu.Language"))).intValue());
        }

        if (ElanLocale.getLocale() == ElanLocale.ENGLISH) {
            menuFile.setMnemonic(KeyEvent.VK_F);
            menuItemFileNew.setMnemonic(KeyEvent.VK_N);
            menuItemFileOpen.setMnemonic(KeyEvent.VK_O);
            menuItemFileExit.setMnemonic(KeyEvent.VK_X);
        } else if (ElanLocale.getLocale() == ElanLocale.DUTCH) {
            menuFile.setMnemonic(KeyEvent.VK_B);
            menuItemFileNew.setMnemonic(KeyEvent.VK_N);
            menuItemFileOpen.setMnemonic(KeyEvent.VK_O);
            menuItemFileExit.setMnemonic(KeyEvent.VK_F);
        }
    }

    private void doExit() {
        // do some warning and saving stuff here
        if ((transcriptionForThisFrame != null) &&
                transcriptionForThisFrame.isChanged()) {
            boolean saveNewCopy = false;

            int response = JOptionPane.showConfirmDialog(null,
                    ElanLocale.getString("Frame.ElanFrame.UnsavedData"),
                    ElanLocale.getString("Message.Warning"),
                    JOptionPane.YES_NO_CANCEL_OPTION);

            if (response == JOptionPane.YES_OPTION) {
                if (transcriptionForThisFrame.getName().equals(TranscriptionImpl.UNDEFINED_FILE_NAME)) {
                    // save as dialog
                    saveNewCopy = true;
                } else {
                    // do a normal save
                    saveNewCopy = false;
                }

                ACM23TranscriptionStore ets = new ACM23TranscriptionStore();
                StoreCommand storeComm = new StoreCommand(ELANCommandFactory.STORE);
                storeComm.execute(transcriptionForThisFrame,
                    new Object[] {
                        ets, new Boolean(false), new Boolean(saveNewCopy),
                        viewerManager.getMultiTierControlPanel()
                                     .getVisibleTiers()
                    });
            } else if ((response == JOptionPane.CANCEL_OPTION) ||
                    (response == JOptionPane.CLOSED_OPTION)) {
                // the user does not want to exit
                return;
            }

            // otherwise exit without saving
        }

        savePreferences();

        // update the opened eaf's administration
        if (allEAFPaths != null) {
            allEAFPaths.remove(thisEAFPath);
            allElanFrames.remove(this);
        }

        // REMINDER (HB): remove document from ELANCommandFactory
        if (transcriptionForThisFrame != null) {
            //stop the backup task, just to be sure
            ((BackupCA) ELANCommandFactory.getCommandAction(transcriptionForThisFrame,
                ELANCommandFactory.BACKUP)).stopBackUp();
            ELANCommandFactory.removeDocument(viewerManager);
            Preferences.removeDocument(transcriptionForThisFrame);

            // remove this elan frame as locale listener
            ElanLocale.removeElanLocaleListener(transcriptionForThisFrame);
            viewerManager.cleanUpOnClose();
            System.runFinalization();
            System.gc();
        }

        if (!exitAllowed || (frameCount > 1)) {
            // more clean up here
            frameCount--;
            dispose();
        } else {
            // close preliminary external launcher 
            mpi.eudico.client.annotator.integration.ExternalLauncher.stop();
            System.exit(0);
        }
    }

    private void savePreferences() {
        // save some transcription specific preference values
        if (layoutManager != null) {
            if (layoutManager.getMultiTierControlPanel() != null) {
                Vector tierOrder = layoutManager.getMultiTierControlPanel()
                                                .getTierOrder();

                if (tierOrder != null) {
                    Preferences.set("TierOrder", tierOrder,
                        transcriptionForThisFrame);
                }

                String activeTierName = layoutManager.getMultiTierControlPanel()
                                                     .getActiveTierName();

                if (activeTierName != null) {
                    Preferences.set("ActiveTierName", activeTierName,
                        transcriptionForThisFrame);
                }
            }

            Preferences.set("LayoutManagerState", layoutManager.getState(),
                transcriptionForThisFrame);
        }

        if (viewerManager != null) {
            Preferences.set("MediaTime",
                viewerManager.getMasterMediaPlayer().getMediaTime(),
                transcriptionForThisFrame);
            Preferences.set("SelectionBeginTime",
                viewerManager.getSelection().getBeginTime(),
                transcriptionForThisFrame);
            Preferences.set("SelectionEndTime",
                viewerManager.getSelection().getEndTime(),
                transcriptionForThisFrame);
            Preferences.set("TimeScaleBeginTime",
                viewerManager.getTimeScale().getBeginTime(),
                transcriptionForThisFrame);
        }

        Preferences.set("Locale", ElanLocale.getLocale(), null);
        Preferences.set("FrameSize", getSize(), null);
        Preferences.set("FrameLocation", getLocation(), null);
    }

    private void loadPreferences() {
        // initialize some transcription specific values
        // invokeLater ensures the viewers are initialized properly before setting values
        SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    Locale savedLocale = (Locale) Preferences.get("Locale", null);

                    if (savedLocale != null) {
                        ElanLocale.setLocale(savedLocale);
                    }

                    Vector tierOrder = (Vector) Preferences.get("TierOrder",
                            transcriptionForThisFrame);

                    if (tierOrder != null) {
                        if (tierOrder.size() > 0) {
                            layoutManager.getMultiTierControlPanel()
                                         .setTierOrder(tierOrder);
                        } else if (transcriptionForThisFrame.getTiers().size() > 0) {
                            Vector tiers = transcriptionForThisFrame.getTiers();
                            Vector tierNames = new Vector(tiers.size());

                            for (int i = 0; i < tiers.size(); i++) {
                                Tier t = (Tier) tiers.get(i);
                                tierNames.add(t.getName());
                            }

                            layoutManager.getMultiTierControlPanel()
                                         .setTierOrder(tierNames);
                        }
                    }

                    String activeTierName = (String) Preferences.get("ActiveTierName",
                            transcriptionForThisFrame);

                    if (activeTierName != null) {
                        layoutManager.getMultiTierControlPanel()
                                     .setActiveTierForName(activeTierName);
                    }

                    Long beginTime = (Long) Preferences.get("SelectionBeginTime",
                            transcriptionForThisFrame);
                    Long endTime = (Long) Preferences.get("SelectionEndTime",
                            transcriptionForThisFrame);

                    if ((beginTime != null) && (endTime != null)) {
                        viewerManager.getSelection().setSelection(beginTime.longValue(),
                            endTime.longValue());
                    }

                    Long mediaTime = (Long) Preferences.get("MediaTime",
                            transcriptionForThisFrame);

                    if (mediaTime != null) {
                        viewerManager.getMasterMediaPlayer().setMediaTime(mediaTime.longValue());
                    }

                    Long timeScaleBeginTime = (Long) Preferences.get("TimeScaleBeginTime",
                            transcriptionForThisFrame);

                    if (timeScaleBeginTime != null) {
                        viewerManager.getTimeScale().setBeginTime(timeScaleBeginTime.longValue());
                    }

                    HashMap layoutMap = (HashMap) Preferences.get("LayoutManagerState",
                            transcriptionForThisFrame);

                    if (layoutMap != null) {
                        layoutManager.setState(layoutMap);
                    }

                    // start the backup thread
                    Integer backupDelay = (Integer) Preferences.get("BackUpDelay",
                            null);

                    if ((backupDelay != null) && (backupDelay.intValue() > 0)) {
                        Command c = ELANCommandFactory.createCommand(transcriptionForThisFrame,
                                ELANCommandFactory.BACKUP);
                        c.execute(ELANCommandFactory.getCommandAction(
                                transcriptionForThisFrame,
                                ELANCommandFactory.BACKUP),
                            new Object[] { backupDelay });
                    }
                }
            });

        layoutManager.doLayout();
    }

    /**
     * DOCUMENT ME!
     *
     * @param arg DOCUMENT ME!
     */
    public static void main(String[] arg) {
        // supress floppy message from web start
        System.out.println("Java version: " +
            System.getProperty("java.version"));
        System.out.println("Runtime version: " +
            System.getProperty("java.runtime.version"));
        mpi.eudico.client.annotator.util.SystemInstallationSecurity.Instance()
                                                                   .go();

        //use java look and feel, so everything (multiple file chooser) looks the same
        //on windows and mac 
        /*
           try {
               UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
           } catch (Exception ex) {
               ex.printStackTrace();
           }
         */
        exitAllowed = true;

        //		String p2p = System.getProperty("P2P");
        //		if ((p2p != null) && (System.getProperty("P2P").equals("true"))) {
        //			mpi.eudico.p2p.ElanP2P.initP2P();
        //		}
        // make sure the directory for Elan data exists, for the time being the dir only contains global preferences
        File dataDir = new File(Constants.ELAN_DATA_DIR);

        if (!dataDir.exists()) {
            dataDir.mkdir();
        }

        // temporary, clean up old crap
        File oldCrap = new File(Constants.STRPROPERTIESFILE);
        oldCrap.delete();
        oldCrap = new File(Constants.USERHOME + Constants.FILESEPARATOR +
                ".elan.pfs");
        oldCrap.delete();

        if ((arg != null) && (arg.length > 0) && (arg[0].length() != 0)) {
            new ElanFrame2(arg[0]);
        } else {
            new ElanFrame2();
        }

        // preliminary external launcher 
        mpi.eudico.client.annotator.integration.ExternalLauncher.start();
    }

    /**
     * Switches between "Metal" and the Mac native Look and Feel. "Metal" on
     * MacOS isn't always behaving well; menus and popup menus  often are not
     * updated correctly etc.
     */
    private void switchMacLF() {
        if (menuMacNativeLF != null) {
            if (menuMacNativeLF.getState()) {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    SwingUtilities.updateComponentTreeUI(this);
                    Preferences.set("UseMacLF", new Boolean(true), null);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            } else {
                try {
                    UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
                    SwingUtilities.updateComponentTreeUI(this);
                    Preferences.set("UseMacLF", new Boolean(false), null);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

    /**
     * Mac OS X specific handling of the main (screen) menu Quit application
     * event. Implementation of MacApplicationListener.
     */
    public void macHandleQuit() {
        doExit();
    }

    /**
     * Mac OS X specific handling of the main (screen) menu About application
     * event. Implementation of MacApplicationListener.
     */
    public void macHandleAbout() {
        if (transcriptionForThisFrame != null) {
            Command c = ELANCommandFactory.createCommand(transcriptionForThisFrame,
                    ELANCommandFactory.ABOUT_DLG);
            c.execute(null, new Object[] { transcriptionForThisFrame });
        } else {
            JOptionPane.showMessageDialog(this,
                (ElanLocale.getString("Menu.Help.AboutText") + "\n\n" +
                ElanLocale.getString("Menu.Help.AboutText.GPL")),
                ElanLocale.getString("Menu.Help.AboutDialog"),
                JOptionPane.PLAIN_MESSAGE,
                new ImageIcon(this.getClass().getResource("/mpi/eudico/client/annotator/resources/EUDICO.gif")));
        }
    }

    public void finalize() {
        System.out.println("Cleaning up Elan frame...");
    }

    /**
     * Listener for ElanFrame WindowEvents
     */
    private class ElanFrameWindowListener extends WindowAdapter {
        // triggered when the window is closed to quit the application
        // handle warnings and save operations in doExit();
        // EXIT WIL BE REPLACED BY CLOSE
        public void windowClosing(WindowEvent e) {
            doExit();
        }
    }

    /*
       private class InitThread extends Thread {
           final String path;
           InitThread(String eafPath) {
               path = eafPath;
           }
           public void run() {
               final IndeterminateProgressMonitor monitor = new IndeterminateProgressMonitor(
                   ElanFrame2.this,
                   true,
                   ElanLocale.getString("Frame.ElanFrame.Progress.Open") + path,
                   false,
                   null);
               new Thread(new Runnable(){
                   public void run() {
                       monitor.show();
                   }
               }).start();
               //monitor.show();
               ElanFrame2.this.initElan();
               monitor.close();
           }
       }
     */
}
