/*
 * @(#)MainWin.java
 *
 * This file is part of webCDwriter - Network CD Writing.
 *
 * Copyright (C) 1999-2003 Jörg P. M. Haeger
 *
 * webCDwriter is free software. See CDcreator.java for details.
 */

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.URL;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;

/**
 * The main window of webCDcreator.
 *
 * @version 20030808
 * @author Jörg P. M. Haeger
 */
class MainWin extends JFrame implements ActionListener {
	final static String
		blankCmd = "cmdBlank",
		burnCmd = "burnCmd",
		changePasswordCmd = "cmdChangePassword",
		copyCmd = "cmdCopy",
		downCmd = "down",
		newDirCmd = "newDirCmd",
		newSessionCmd = "cmdNewSession",
		openProjectCmd = "cmdOpenProject",
		quitCmd = "quitCmd",
		removeCmd = "removeCmd",
		renameCmd = "cmdRename",
		saveProjectCmd = "cmdSaveProject",
		setBootImageCmd = "cmdSetBootImage",
		showHelpCmd = "showHelpCmd",
		showInfoCmd = "showInfoCmd",
		showLogWin = "cmdShowLogWin",
		showStatus = "showStatus",
		transferCmd = ">>",
		upCmd = "up";

	final static String
		chinese = "Chinese",
		dutch = "Nederlands",
		german = "Deutsch",
		english = "English",
		frensh = "Français",
		hungarian = "Hungarian",
		italian = "Italiano",
		korean = "Korean",
		norwegian = "Norwegian",
		polish = "Polski",
		portuguese = "Português",
		russian = "Russian",
		spanish = "Español",
		swedish = "Swedish",
		ukrainian = "Ukrainian";

	// components
//	private RootPaneContainer rootPaneContainer;
	private JMenuBar menuBar;
	private JTree tree, CDTree;
	private JComboBox mediumBox;
	private JLabel mediumLabel;
	private JPanel mediumPanel;
	private CDView theCDView;
	private TreeTableModelAdapter CDViewModel;
	private JScrollPane treeScroller, CDTreeScroller;
	private JButton
		burnButton,
		copyButton,
		downButton,
		newDirButton,
		removeButton,
		setBootImageButton,
		upButton;
	SessionSizeView sessionSizeView;
	private JPanel sessionSizePanel;

	// models
	private DirTreeNode fsNode, homeNode = null;
	private CDNode CDRoot;
	private DefaultTreeModel fsTreeModel, CDTreeModel;

	ActionListener actionListener;
	static DirTreeNode bootImageNode = null;
	MainWin mainWin;
	boolean serverUpToDate = false;

	MainWin() {
		super(Version.product
			+ (Version.version.length() < 8?
				" " + Version.version: ""));
		getContentPane().setLayout(LM);
		addWindowListener(new WindowAdapter() {
			public void windowClosed(WindowEvent e) {
				if (CDcreator.applet == null)
					System.exit(0);
				else
					CDcreator.applet.closeMainWin();
			}
			public void windowClosing(WindowEvent e) {
				e.getWindow().dispose();
			}
		});

		createMenuBar();
		setJMenuBar(menuBar);

		fsNode = new DirTreeNode(i18n("sources"));
		fsTreeModel = new DefaultTreeModel(fsNode, true);

		// add the file system roots
/*		File[] roots = File.listRoots();
		for (int i = 0; i < roots.length; i++) {
			DirTreeNode rootNode = new DirTreeNode(
				new SecFile(roots[i] + File.separator), true);
			fsTreeModel.insertNodeInto(
				rootNode, fsNode,
				fsTreeModel.getChildCount(fsNode));
		}
*/
		boolean defaultSources = true;
		try {
			String[] names = {
				System.getProperty("user.home")
					+ File.separatorChar + "webCDcreator.cfg",
				"C:\\webCDcreator.cfg",
				System.getProperty("user.home")
					+ File.separatorChar + ".webCDcreator.cfg",
				"/etc/webCDcreator.cfg"
			};
			for (int i = 0; i < names.length; i++) {
//				System.out.println(names[i]);
				File configFile = new File(names[i]);
				if (!configFile.exists())
					continue;

				BufferedReader reader
					= new BufferedReader(
						new FileReader(configFile));
				while (true) {
					String line = reader.readLine();
					if (line == null)
						break;

					StreamTokenizer tokenizer
						= new StreamTokenizer(
							new StringReader(line));
//					tokenizer.resetSyntax();
//					tokenizer.whitespaceChars(0, 32);
					tokenizer.wordChars(33, 255);
					tokenizer.ordinaryChar('=');
					tokenizer.ordinaryChar(',');

					if (tokenizer.nextToken() != tokenizer.TT_WORD)
						break;
					if (!tokenizer.sval.equals("sources"))
						break;

					if (tokenizer.nextToken() != '=')
						break;

					while (true) {
						if (tokenizer.nextToken() != tokenizer.TT_WORD)
							break;

//						System.out.println(tokenizer.sval);
						defaultSources = false;
						DirTreeNode rootNode = new DirTreeNode(
							new SecFile(tokenizer.sval), true);
						rootNode.setUserObject(tokenizer.sval);
						fsTreeModel.insertNodeInto(
							rootNode, fsNode,
							fsTreeModel.getChildCount(fsNode));

						if (tokenizer.nextToken() != ',')
							break;
					}
				}
				break;
			}
		}
		catch (Exception e) {
		}

		boolean windowsSystem = false;
		if (defaultSources)
		for (char ch = 'C'; ch <= 'Z'; ch++) {
			char chars[] = { ch, ':', File.separatorChar };
			String driveName = new String(chars);
			File drive = new SecFile(driveName);

			if (CDcreator.isNetscapeVM())
				// Netscape File.list() bug workaround
				drive = new SecFile(driveName + ".");

			if (drive.exists()) {
				windowsSystem = true;
				DirTreeNode rootNode = new DirTreeNode(
					drive, true);
				if (ch == 'P')
					rootNode.setUserObject(
						System.getProperty("user.name")
						+ " (" + driveName + ")");
				else
					rootNode.setUserObject(driveName);
				fsTreeModel.insertNodeInto(
					rootNode, fsNode,
					fsTreeModel.getChildCount(fsNode));
			}
		}

		if (defaultSources && !windowsSystem) {
			// UNIX
			DirTreeNode rootNode
				= new DirTreeNode(new SecFile("/"));
			rootNode.setUserObject("/");
			fsTreeModel.insertNodeInto(
				rootNode, fsNode,
				fsTreeModel.getChildCount(fsNode));

			if (new File("/home").exists()) {
				homeNode = new DirTreeNode(new SecFile("/home"));
				homeNode.setUserObject(i18n("homeDirs"));
				fsTreeModel.insertNodeInto(
					homeNode, fsNode,
					fsTreeModel.getChildCount(fsNode));
			}
		}

		if (defaultSources) {
			// add the home directory of the JVM
			String homeDir = System.getProperty("user.home");
			if (homeDir.endsWith("/.netscape"))
				homeDir = homeDir.substring(
					0, homeDir.length() - 10);
			DirTreeNode homeDirNode
				= new DirTreeNode(new SecFile(homeDir));
			homeDirNode.setUserObject(homeDir);
			fsTreeModel.insertNodeInto(
				homeDirNode, fsNode,
				fsTreeModel.getChildCount(fsNode));
		}

		tree = new JTree(fsTreeModel);
		tree.setSelectionModel(new DefaultTreeSelectionModel());
		tree.addTreeWillExpandListener(treeWillExpandListener);
		tree.putClientProperty("JTree.lineStyle", "Angled");
		treeScroller = new JScrollPane(tree);
		getContentPane().add(treeScroller);

		copyButton = new JButton(transferCmd);
		copyButton.addActionListener(this);
		copyButton.setToolTipText(i18n("TTcopy"));
		getContentPane().add(copyButton);

		// mediumPanel
		mediumBox = new JComboBox(Mode.media);
		mediumPanel = new JPanel();
		mediumPanel.setLayout(
			new BoxLayout(mediumPanel, BoxLayout.X_AXIS));
		mediumPanel.setBorder(
			BorderFactory.createRaisedBevelBorder());
		mediumPanel.add(Box.createHorizontalStrut(10));
		mediumLabel = new JLabel(i18n("MWMedium"));
		mediumPanel.add(mediumLabel);
		mediumPanel.add(Box.createHorizontalStrut(10));
		mediumPanel.add(mediumBox);
		mediumPanel.add(Box.createHorizontalGlue());
		getContentPane().add(mediumPanel);

		createCDView();

		removeButton = new JButton(getIcon("editdelete.png"));
		removeButton.setActionCommand(removeCmd);
		removeButton.addActionListener(this);
		removeButton.setToolTipText(i18n("TTcut"));
		getContentPane().add(removeButton);

		newDirButton = new JButton(getIcon("folder_new.png"));
		newDirButton.setActionCommand(newDirCmd);
		newDirButton.addActionListener(this);
		newDirButton.setToolTipText(i18n("TTnewDir"));
		getContentPane().add(newDirButton);

		setBootImageButton = new JButton(getIcon("boot.jpg"));
		setBootImageButton.setActionCommand(setBootImageCmd);
		setBootImageButton.addActionListener(this);
		setBootImageButton.setToolTipText(i18n("TTsetBootImage"));
//		setBootImageButton.setVisible(false);
		getContentPane().add(setBootImageButton);

		burnButton = new JButton(getIcon("burn.png"));
		burnButton.setActionCommand(burnCmd);
		burnButton.addActionListener(this);
		burnButton.setToolTipText(i18n("burnCmd"));
		getContentPane().add(burnButton);

		upButton = new JButton(getIcon("up.png"));
		upButton.setActionCommand(upCmd);
		upButton.addActionListener(this);
		upButton.setToolTipText(i18n("MainWin.upTip"));
		getContentPane().add(upButton);

		downButton = new JButton(getIcon("down.png"));
		downButton.setActionCommand(downCmd);
		downButton.addActionListener(this);
		downButton.setToolTipText(i18n("MainWin.downTip"));
		getContentPane().add(downButton);

		actionListener = this;
		mainWin = this;
	}

	public void actionPerformed(ActionEvent e) {
		showDebugInfo("action: " + e.getActionCommand());

		if (CDcreator.isNetscapeVM())
		try {
			netscape.security.PrivilegeManager
				.enablePrivilege("UniversalFileRead");
			netscape.security.PrivilegeManager
				.enablePrivilege("UniversalPropertyRead");
		}
		catch (Exception e2) {
		}

		if (e.getActionCommand().equals(blankCmd))
			blank();
		else
		if (e.getActionCommand().equals(burnCmd))
			burnSession();
		else
		if (e.getActionCommand().equals(changePasswordCmd)) {
			if (!login())
				return;

			ChangePasswordDialog dialog = new ChangePasswordDialog();
			center(dialog);
			dialog.show();
			if (dialog.wasCanceled())
				return;

			try {
				new ChangePassword(dialog.getPassword()).exec();
			} catch (CommandError cmdErr) {
			}
		}
		else
		if (e.getActionCommand().equals(chinese)
			|| e.getActionCommand().equals(dutch)
			|| e.getActionCommand().equals(english)
			|| e.getActionCommand().equals(frensh)
			|| e.getActionCommand().equals(german)
			|| e.getActionCommand().equals(hungarian)
			|| e.getActionCommand().equals(italian)
			|| e.getActionCommand().equals(korean)
			|| e.getActionCommand().equals(norwegian)
			|| e.getActionCommand().equals(polish)
			|| e.getActionCommand().equals(portuguese)
			|| e.getActionCommand().equals(russian)
			|| e.getActionCommand().equals(spanish)
			|| e.getActionCommand().equals(swedish)
			|| e.getActionCommand().equals(ukrainian)) {
			java.util.Locale locale = CDcreator.locale;
			String lang = e.getActionCommand();
			if (lang.equals(chinese))
				locale = new java.util.Locale("zh", "TW");
			else
			if (lang.equals(dutch))
				locale = new java.util.Locale("nl", "NL");
			else
			if (lang.equals(english))
				locale = new java.util.Locale("en", "US");
			else
			if (lang.equals(frensh))
				locale = new java.util.Locale("fr", "FR");
			else
			if (lang.equals(german))
				locale = new java.util.Locale("de", "DE");
			else
			if (lang.equals(hungarian))
				locale = new java.util.Locale("hu", "HU");
			else
			if (lang.equals(italian))
				locale = new java.util.Locale("it", "IT");
			else
			if (lang.equals(korean))
				locale = new java.util.Locale("ko", "KR");
			else
			if (lang.equals(norwegian))
				locale = new java.util.Locale("no", "NO");
			else
			if (lang.equals(polish))
				locale = new java.util.Locale("pl", "PL");
			else
			if (lang.equals(portuguese))
				locale = new java.util.Locale("pt", "BR");
			else
			if (lang.equals(russian))
				locale = new java.util.Locale("ru", "RU");
			else
			if (lang.equals(spanish))
				locale = new java.util.Locale("es", "ES");
			else
			if (lang.equals(swedish))
				locale = new java.util.Locale("sv", "SE");
			else
			if (lang.equals(ukrainian))
				locale = new java.util.Locale("uk", "UA");

			java.util.Locale oldLocale = CDcreator.locale;
			CDcreator.setLocale2(locale);

			try {
				Font font = new JButton().getFont();
				String sample = i18n("FDTextSample");
				int pos = font.canDisplayUpTo(sample);
				if (pos != -1 && pos < sample.length()) {
//					setUIFont(new javax.swing.plaf.FontUIResource(
//						"Dialog", Font.PLAIN, 30));
					new FontDialog().setVisible(true);
					showFontInfo();
					CDcreator.setLocale2(oldLocale);
				}
			} catch (NoSuchMethodError e2) {}

			createMenuBar();
			fsNode.setUserObject(i18n("sources"));
			if (homeNode != null)
				homeNode.setUserObject(i18n("homeDirs"));
			updateCDRoot();
			copyButton.setToolTipText(i18n("TTcopy"));
			mediumLabel.setText(i18n("MWMedium"));
			removeButton.setToolTipText(i18n("TTcut"));
			newDirButton.setToolTipText(i18n("TTnewDir"));
			setBootImageButton.setToolTipText(i18n("TTsetBootImage"));
			burnButton.setToolTipText(i18n("burnCmd"));
			downButton.setToolTipText(i18n("MainWin.downTip"));
			upButton.setToolTipText(i18n("MainWin.upTip"));
			sessionSizeView.setToolTipText(CDcreator.i18n("TTsessionSize"));
		}
		else
		if (e.getActionCommand().equals(copyCmd))
			burnCopy();
		else
		if (e.getActionCommand().equals(newDirCmd)) {
			TreePath path;
			if (CDTree.isSelectionEmpty())
//				CDTree.setSelectionRow(0);
				path = new TreePath(
					CDTree.getModel().getRoot());
			else
				path = CDTree.getSelectionPath();
			DirTreeNode CDnode = (DirTreeNode)path
				.getLastPathComponent();
			if (CDnode.isLeaf())
				CDnode = (DirTreeNode)CDnode.getParent();
			if (CDnode == null || CDnode.isLeaf()) {
				JOptionPane.showMessageDialog(
					CDcreator.mainWin,
					i18n("MWDestinationIsNotAFolder"),
					i18n("error"),
					JOptionPane.ERROR_MESSAGE);
				return;
			}

			String name = (String)JOptionPane.showInputDialog(
				this, i18n("NFDName"), i18n("NFDTitle"),
				JOptionPane.QUESTION_MESSAGE, null, null,
				i18n("NFDDefaultNewFolderName"));
			if (name == null || name.length() == 0)
				return;

			int count = CDTreeModel.getChildCount(CDnode);
			for (int i = 0; i < count; i++) {
				if (CDTreeModel.getChild(CDnode, i).toString()
						.equals(name))
					return;
			}

			DirTreeNode newNode = new CDNode(name);
			CDTreeModel.insertNodeInto(newNode, CDnode, count);
			path = path.pathByAddingChild(newNode);
			Project.mkdir(path);
			CDTree.startEditingAtPath(path);
			serverUpToDate = false;
		}
		else
		if (e.getActionCommand().equals(newSessionCmd)) {
			if (typeSelection(true)) {
				State.resetSession();
				copyButton.setEnabled(true);
				getContentPane().doLayout();
				resetCDView();
			}
		}
		else
		if (e.getActionCommand().equals(openProjectCmd)) {
			if (!login())
				return;

			OpenDialog dialog = new OpenDialog();
			center(dialog);
			dialog.show();
			if (dialog.wasCanceled())
				return;

			Options.reset();
			resetCDView();
			copyButton.setEnabled(true);
			getContentPane().doLayout();
			try {
				new LoadProject().exec();
			} catch (CommandError cmdErr) {}
			updateCDRoot();
			sessionSizeView.recount();
			serverUpToDate = dialog.getNumOfTracks() > 0;
		}
		else
		if (e.getActionCommand().equals(quitCmd)) {
			if (CDcreator.applet == null)
				System.exit(0);
		}
		else
		if (e.getActionCommand().equals(removeCmd)) {
			TreePath paths[] = CDTree.getSelectionPaths();
			if (paths == null)
				return;
			for (int i = 0; i < paths.length; i++)
				remove(paths[i]);
			serverUpToDate = false;
			if (Mode.burnImageFile()
				&& CDRoot.getChildCount() == 0)
				copyButton.setEnabled(true);
		}
		else
		if (e.getActionCommand().equals(renameCmd)) {
			if (CDTree.isSelectionEmpty())
				return;

			TreePath path = CDTree.getSelectionPath();
			DirTreeNode CDnode = (DirTreeNode)path
				.getLastPathComponent();

			String name = (String)JOptionPane.showInputDialog(
				this, i18n("RDNewName"), i18n("RDTitle"),
				JOptionPane.QUESTION_MESSAGE, null, null,
				CDnode.toString());
			if (name == null || name.length() == 0)
				return;

			DirTreeNode parent = (DirTreeNode)CDnode.getParent();
			if (parent == null)
				return;
			int count = CDTreeModel.getChildCount(parent);
			for (int i = 0; i < count; i++) {
				if (CDTreeModel.getChild(parent, i).toString()
						.equals(name))
					return;
			}

			Project.rename(CDTree.getSelectionPath(), name);
			CDnode.setUserObject(name);
//			CDView.updateUI();
//			CDViewModel.fireTableRowsUpdated(
//				0, CDViewModel.getRowCount());
			CDTreeModel.nodeChanged(CDnode);
			serverUpToDate = false;
		}
		else
		if (e.getActionCommand().equals(saveProjectCmd)) {
			if (!login())
				return;

			SaveDialog dialog = new SaveDialog();
			center(dialog);
			dialog.show();
			if (dialog.wasCanceled())
				return;

			updateCDRoot();
			try {
				new SaveProject().exec();
				if (dialog.isStoreSet()) {
					putSession();
					new CloseSession().exec();
				}
			} catch (CommandError cmdErr) {
				try {
					new CloseSession().exec();
				} catch (CommandError cmdErr2) {}
			}
		}
		else
		if (e.getActionCommand().equals(setBootImageCmd)) {
			TreePath paths[] = CDTree.getSelectionPaths();
			if (paths == null)
				return;
			DirTreeNode CDnode = (DirTreeNode)paths[0]
				.getLastPathComponent();
			if (!CDnode.isLeaf())
				return;
			if (bootImageNode == CDnode)
				bootImageNode = null;
			else
				bootImageNode = CDnode;
			((DefaultTreeModel)CDTree.getModel())
				.nodeChanged(CDnode);
		}
		else
		if (e.getActionCommand().equals(showHelpCmd))
			CDcreator.showDocument("doc/index.html");
		else
		if (e.getActionCommand().equals(showInfoCmd))
			showAbout();
		else
		if (e.getActionCommand().equals(showLogWin))
			new LogWin().show();
		else
		if (e.getActionCommand().equals(showStatus)) {
			try {
				URL url = new URL("http",
					CDcreator.serverName,
					CDcreator.serverPortNo, "");
				CDcreator.showDocument(url);
			} catch (java.net.MalformedURLException urlExp) {
			}
		}
		else
		if (e.getActionCommand().equals(transferCmd)) {
			TreePath paths[] = tree.getSelectionPaths();
			if (paths == null)
				return;
			int n = paths.length;
			if (Mode.burnImageFile())
				if (CDRoot.getChildCount() > 0)
					n = 0;
				else
					if (n > 1)
						n = 1;
			try {
				for (int i = 0; i < n; i++)
					transfer(paths[i]);
			} catch (Exception e2) {
			}
			serverUpToDate = false;
			if (Mode.burnImageFile()
				&& CDRoot.getChildCount() > 0)
				copyButton.setEnabled(false);
			sessionSizeView.recount();
		}
		else
		if (e.getActionCommand().equals(upCmd)
			|| e.getActionCommand().equals(downCmd)) {
			if (CDTree.isSelectionEmpty())
				return;

			TreePath path = CDTree.getSelectionPath();
			DirTreeNode CDnode
				= (DirTreeNode)path.getLastPathComponent();
			MutableTreeNode parent = (MutableTreeNode)CDnode.getParent();
			if (parent == null)
				return;

			DefaultTreeModel treeModel
				= (DefaultTreeModel)CDTree.getModel();
			int p = treeModel.getIndexOfChild(parent, CDnode);
			if (e.getActionCommand().equals(upCmd)) {
				if (--p < 0)
					return;
			}
			else
				if (++p >= treeModel.getChildCount(parent))
					return;

			treeModel.removeNodeFromParent(CDnode);
			treeModel.insertNodeInto(CDnode, parent, p);
			CDTree.setSelectionPath(path);
			CDTree.scrollPathToVisible(path);
			serverUpToDate = false;
		}
	}

	public void addServerExports() {
		// add nodes to the software archive on the server
		File[] serverFiles = new ServerFile("/").listFiles();
		for (int i = 0; i < serverFiles.length; i++) {
			DirTreeNode serverNode = new DirTreeNode(serverFiles[i]);
//			serverNode.setUserObject(i18n("archiveOnServer"));
			fsTreeModel.insertNodeInto(
				serverNode, fsNode,
				fsTreeModel.getChildCount(fsNode));
		}
	}

	void blank() {
		JPanel p = new JPanel();
		p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));

		JRadioButton fastBox = new JRadioButton(i18n("ODfast"));
		fastBox.setSelected(true);
		p.add(fastBox);

		JRadioButton allBox = new JRadioButton(i18n("ODall"));
		p.add(allBox);
		p.add(Box.createRigidArea(new Dimension(0, 5)));

		ButtonGroup group = new ButtonGroup();
		group.add(fastBox);
		group.add(allBox);

		JComboBox speedBox = OptionsDialog.createSpeedBox();
		p.add(Dialog.createLabelItemBox(
			new JLabel(i18n("speed")), speedBox));

		String[] options = { i18n("cancel"), i18n("OK") };
		if (JOptionPane.showOptionDialog(this, p,
			i18n(blankCmd),
			JOptionPane.OK_CANCEL_OPTION,
			JOptionPane.QUESTION_MESSAGE,
			null, options, options[1]) != 1)
			return;

		String speed = (String)speedBox.getSelectedItem();
		Options.speed = Integer.parseInt(
			speed.substring(0, speed.indexOf('x')));
		try {
			new Blank(allBox.isSelected()).exec();
		} catch (CommandError cmdErr) {};
	}

	void burnCopy() {
		Mode.source = Mode.copy;
		burnSession();
		Mode.source = Mode.current;
	}

	private void burnSession() {
		try {
			if (Mode.type == Mode.audio
				|| Mode.source == Mode.copy)
				Options.closeCD = true;

			OptionsDialog options = new OptionsDialog();
			options.pack();
			center(options);
			while (true) {
				options.show();
				if (options.wasCanceled())
					return;

				if (Options.blankTOC || Options.format) {
					String[] options2 = {
						i18n("MainWin.back"),
						i18n("MainWin.continue") };
					int result = JOptionPane.showOptionDialog(
						CDcreator.mainWin,
						i18n("MainWin.wantToOverwrite"),
						i18n("warning"),
						JOptionPane.DEFAULT_OPTION,
						JOptionPane.WARNING_MESSAGE,
						null, options2, options2[0]);
					if (result == 1)
						break;
				}
				else
					break;
			}

			if (!Mode.copyCD())
				putSession();

			Log.clear();
			if (Mode.copyCD())
				new BurnCopy().exec();
			else
				new BurnSession().exec();
//			new CloseSession().exec();
		}
		catch (CommandError cmdErr) {
			try {
				if (!Mode.copyCD())
					new CloseSession().exec();
			}
			catch (CommandError cmdErr2) {
			}
		}
	}

	public void center(Component c) {
		Rectangle r0 = getBounds();
		Rectangle r1 = c.getBounds();
		c.setBounds(r0.x + (r0.width - r1.width) / 2,
			r0.y + (r0.height - r1.height) / 2,
			r1.width, r1.height);
	}

	private void checkAudioFile(File file) throws Exception {
		if (file.length() <= 44) {
			new JOptionPane(
				file + "\n" + i18n("incompleteAudioFile"),
				JOptionPane.ERROR_MESSAGE,
				JOptionPane.DEFAULT_OPTION)
				.createDialog(CDcreator.mainWin,
					i18n("titleNoAudioFile")).show();
			throw new Exception("no or incomplete audio file");
		}

		if (file instanceof ServerFile) {
			int type = ((ServerFile)file).getType();
			if (type == ServerFile.WAV
					|| (type == ServerFile.MP3 && CDcreator.mp3Support)
					|| (type == ServerFile.OGG && CDcreator.oggSupport))
				return;
			else
				throw new Exception("invalid audio file");
		}

		if (file.getName().toLowerCase().endsWith(".wav")) {
			Wave wave = new Wave(file);
/*			if (wave.bytesPerSample != 4
				|| wave.channels != 2
				|| wave.frequency != 44100)
				throw new Exception("invalid audio file");
*/			return;
		}

		if (file.getName().toLowerCase().endsWith(".mp3")
				&& CDcreator.mp3Support) {
			new MP3(file);
			return;
		}

		if (file.getName().toLowerCase().endsWith(".ogg")
				&& CDcreator.oggSupport) {
			new Ogg(file);
			return;
		}

		new Wave(file);

		throw new Exception("no or unknown audio file");
	}

	private void checkFile(File file) throws Exception {
		if (Mode.burnImageFile()) {
			if (file.isDirectory())
				throw new Exception("no imagefile");
			return;
		}

		if (Mode.audioCD())
			try {
				checkAudioFile(file);
			} catch (Exception e) {
				new JOptionPane(
					file + "\n" + i18n("noAudioFile"),
					JOptionPane.ERROR_MESSAGE,
					JOptionPane.DEFAULT_OPTION)
					.createDialog(CDcreator.mainWin,
						i18n("titleNoAudioFile")).show();
				throw new Exception("no audio file");
			}
	}

	private void createCDView() {
		CDRoot = new CDNode("CD");
		Project.setCDRoot(CDRoot);

		CDTreeModel = new FileSystemModel(CDRoot, true);
		CDTreeModel.addTreeModelListener(new MyTreeModelListener());
		theCDView = new CDView((FileSystemModel)CDTreeModel);
		CDViewModel = (TreeTableModelAdapter)theCDView.getModel();
		SessionSizeView.tableModel
			= (TreeTableModelAdapter)theCDView.getModel();

		theCDView.addMouseListener(new MouseAdapter() {
			private void handle(MouseEvent e) {
				if (!e.isPopupTrigger())
					return;

				int row = theCDView.rowAtPoint(
					new Point(e.getX(), e.getY()));
				theCDView.setRowSelectionInterval(row, row);

				JPopupMenu menu = new JPopupMenu();

				JMenuItem item2;
				item2 = new JMenuItem(i18n(newDirCmd));
				item2.setActionCommand(newDirCmd);
				item2.addActionListener(actionListener);
				item2.setEnabled(Mode.makeISOImage());
				menu.add(item2);

				item2 = new JMenuItem(i18n(removeCmd));
				item2.setActionCommand(removeCmd);
				item2.addActionListener(actionListener);
				menu.add(item2);

				item2 = new JMenuItem(i18n(renameCmd));
				item2.setActionCommand(renameCmd);
				item2.addActionListener(actionListener);
				menu.add(item2);

				item2 = new JMenuItem(i18n(setBootImageCmd));
				item2.setActionCommand(setBootImageCmd);
				item2.addActionListener(actionListener);
				item2.setEnabled(Mode.makeISOImage());
				menu.add(item2);

				menu.show(theCDView, e.getX()-0, e.getY()-0);
			}
			public void mousePressed(MouseEvent e) {
				handle(e);
			}
			public void mouseReleased(MouseEvent e) {
				handle(e);
			}
		});
		theCDView.getColumnModel().getColumn(1).setMaxWidth(70);
		theCDView.setSelectionMode(
			ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		CDTree = theCDView.getTree();
		((javax.swing.JLabel)theCDView.getDefaultRenderer(String.class))
			.setHorizontalAlignment(SwingConstants.RIGHT);

		// renderer
		CDTree.setCellRenderer(
			new DefaultTreeCellRenderer() {
				private Icon icon = MainWin.getIcon("boot.jpg");
				public Icon getLeafIcon() {
					if (isBootImage())
						return icon;
					else
						return super.getLeafIcon();
				}
				public Color getTextNonSelectionColor() {
					if (isBootImage())
						return Color.red;
					else
						return super
						.getTextNonSelectionColor();
				}
				private boolean isBootImage() {
					return bootImageNode != null
					&& super.getText()
						== bootImageNode.toString();
				}
			});

		// editor
//		CDTree.setEditable(true);
		DefaultCellEditor cellEditor = new DefaultCellEditor(
			new MyTextField()) {
				public boolean shouldSelectCell(
					java.util.EventObject event) {
					boolean retValue = super.shouldSelectCell(event);
					getComponent().requestFocus();
					return retValue;
				}
			};
		cellEditor.setClickCountToStart(1);
		CDTree.setCellEditor(
			new DefaultTreeCellEditor(CDTree,
//				(DefaultTreeCellRenderer)CDTree.getCellRenderer(),
				new DefaultTreeCellRenderer(), cellEditor) {
				protected void prepareForEditing() {
					Version.debug("cellEditor", "prepareForEditing()");
					super.prepareForEditing();
					((JTextField)((DefaultCellEditor)realEditor)
						.getComponent()).selectAll();
				}
				public boolean stopCellEditing() {
					Version.debug("cellEditor", "stopCellEditing()");
					return super.stopCellEditing();
				}
			});

		CDTree.setRootVisible(true);
		CDTree.putClientProperty("JTree.lineStyle", "Angled");

		CDTree.addTreeExpansionListener(new TreeExpansionListener() {
			public void treeExpanded(TreeExpansionEvent event) {
				sessionSizeView.recount();
			}
			public void treeCollapsed(TreeExpansionEvent event) {
			}
		});

		if (CDTreeScroller != null)
			getContentPane().remove(CDTreeScroller);

		CDTreeScroller = new JScrollPane(theCDView);
		getContentPane().add(CDTreeScroller);

		if (sessionSizePanel != null)
			getContentPane().remove(sessionSizePanel);

		sessionSizeView = new SessionSizeView();
		sessionSizePanel = new JPanel();
		sessionSizePanel.setLayout(
			new BoxLayout(sessionSizePanel, BoxLayout.X_AXIS));
		sessionSizePanel.setBorder(
			BorderFactory.createRaisedBevelBorder());
		sessionSizePanel.add(Box.createHorizontalStrut(10));
		sessionSizePanel.add(sessionSizeView);
		getContentPane().add(sessionSizePanel);
	}

	void createMenuBar() {
		if (menuBar == null)
			menuBar = new JMenuBar();
		else
			menuBar.removeAll();

		JMenu menu;
		JMenuItem item;

		menu = new JMenu(i18n("file"));

			item = new JMenuItem(newSessionCmd);
			item.addActionListener(this);
			menu.add(item);

			item = new JMenuItem(openProjectCmd);
			item.addActionListener(this);
			menu.add(item);

			menu.add(new JSeparator());

			item = new JMenuItem(saveProjectCmd);
			item.addActionListener(this);
			menu.add(item);

			menu.add(new JSeparator());

			item = new JMenuItem(quitCmd);
			item.addActionListener(this);
			if (CDcreator.applet != null)
				item.addActionListener(CDcreator.applet);
			menu.add(item);

		menuBar.add(menu);

		menu = new JMenu(i18n("view"));

			item = new JMenuItem(showStatus);
			item.addActionListener(this);
//			item.setEnabled(CDcreator.isApplet());
			menu.add(item);

			item = new JMenuItem(showLogWin);
			item.addActionListener(this);
			menu.add(item);

			JMenu menu2 = new JMenu(i18n("language"));

				item = new JMenuItem(chinese);
				item.addActionListener(this);
				menu2.add(item);

				item = new JMenuItem(german);
				item.addActionListener(this);
				menu2.add(item);

				item = new JMenuItem(english);
				item.addActionListener(this);
				menu2.add(item);

				item = new JMenuItem(spanish);
				item.addActionListener(this);
				menu2.add(item);

				item = new JMenuItem(frensh);
				item.addActionListener(this);
				menu2.add(item);

				item = new JMenuItem(hungarian);
				item.addActionListener(this);
				menu2.add(item);

				item = new JMenuItem(italian);
				item.addActionListener(this);
				menu2.add(item);

				item = new JMenuItem(korean);
				item.addActionListener(this);
				menu2.add(item);

				item = new JMenuItem(dutch);
				item.addActionListener(this);
				menu2.add(item);

				item = new JMenuItem(norwegian);
				item.addActionListener(this);
				menu2.add(item);

				item = new JMenuItem(polish);
				item.addActionListener(this);
				menu2.add(item);

				item = new JMenuItem(portuguese);
				item.addActionListener(this);
				menu2.add(item);

				item = new JMenuItem(russian);
				item.addActionListener(this);
				menu2.add(item);

				item = new JMenuItem(swedish);
				item.addActionListener(this);
				menu2.add(item);

				item = new JMenuItem(ukrainian);
				item.addActionListener(this);
				menu2.add(item);

			menu.add(menu2);

		menuBar.add(menu);

		menu = new JMenu(i18n("action"));

			item = new JMenuItem(blankCmd);
			item.addActionListener(this);
			menu.add(item);

			item = new JMenuItem(copyCmd);
			item.addActionListener(this);
			item.setEnabled(CDcreator.copySupport);
			if (CDcreator.cdrdao)
				item.setText(i18n("MainMenu.action.copy"));
			menu.add(item);

			item = new JMenuItem(burnCmd);
			item.addActionListener(this);
			menu.add(item);

		menuBar.add(menu);

		menu = new JMenu(i18n("settings"));

			item = new JMenuItem(changePasswordCmd);
			item.addActionListener(this);
			menu.add(item);

		menuBar.add(menu);

		menu = new JMenu(i18n("help"));

			item = new JMenuItem(showHelpCmd);
			item.addActionListener(this);
			menu.add(item);

			item = new JMenuItem(showInfoCmd);
			item.addActionListener(this);
			item.setText(i18n("about") + " "
				+ Version.product + "...");
			menu.add(item);

		menuBar.add(menu);
		menuBar.updateUI();
	}

	private String getCDTypeStr() {
		String typeStr;
		if (Mode.makeISOImage()) {
			typeStr = i18n("destDataCD");
			newDirButton.setEnabled(true);
			setBootImageButton.setEnabled(true);
		}
		else {
			newDirButton.setEnabled(false);
			setBootImageButton.setEnabled(false);
			if (Mode.audioCD())
				typeStr = i18n("destAudioCD");
			else
				typeStr = i18n("destImageCD");
		}
		if (State.sessionID != State.none)
			typeStr = typeStr + " \"" + State.sessionID + '"';
		return typeStr;
	}

/*	public Container getContentPane() {
		return rootPaneContainer.getContentPane();
	}
*/
	static Icon getIcon(String name) {
		if (name.endsWith(".png") && CDcreator.isNetscapeVM())
			name = name.substring(0, name.length() - 3) + "jpg";

		URL url = CDcreator.getURL("icons/" + name);
		if (url == null)
			return null;
		return new ImageIcon(url);
	}

	static String i18n(String key) {
		return CDcreator.i18n(key);
	}

	boolean login() {
		if (State.userPassword != State.none)
			return true;

		LoginDialog login = new LoginDialog();
		center(login);
		login.show();
		return !login.wasCanceled();
	}

	void putSession() throws CommandError {
		State.numOfFiles = 0;
		State.numOfTracks = 0;
		if (Mode.serverSession() || serverUpToDate)
			new OpenSession().exec();
		else
			new NewSession().exec();

		if (State.numOfFiles == 0
			&& State.numOfTracks == 0)
			if (Mode.makeISOImage())
				new PutFiles(CDRoot,
					sessionSizeView.getKBytesNum()).exec();
			else
				new PutTracks(CDRoot,
					sessionSizeView.getKBytesNum()).exec();

		serverUpToDate = true;
	}

	void remove(TreePath treePath) {
		showDebugInfo("remove: " + treePath.toString());

		DirTreeNode CDnode = (DirTreeNode)treePath
			.getLastPathComponent();
		if (CDnode.getParent() == null)
			return;
		((DefaultTreeModel)CDTree.getModel())
			.removeNodeFromParent(CDnode);
		Project.remove(treePath);
		sessionSizeView.recount();
	}

	private void resetCDView() {
		bootImageNode = null;
		CDRoot = new CDNode(getCDTypeStr());
		CDTreeModel.setRoot(CDRoot);
//		CDViewModel.fireTableStructureChanged();
		Project.setCDRoot(CDRoot);
		sessionSizeView.recount();
	}

	public static void setUIFont(javax.swing.plaf.FontUIResource f) {
		java.util.Enumeration keys = UIManager.getDefaults().keys();
		while (keys.hasMoreElements()) {
			Object key = keys.nextElement();
			Object value = UIManager.get(key);
			if (value instanceof javax.swing.plaf.FontUIResource) {
				System.out.println(key + " <-> " + value);
				UIManager.put(key, f);
			}
		}
	}

	void showAbout() {
		JPanel panel = new JPanel();
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		panel.add(new JLabel(Version.product + " " + Version.version));

		JTabbedPane tabbedPane = new JTabbedPane();
		tabbedPane.setPreferredSize(new Dimension(440, 280));
		tabbedPane.setAlignmentX(LEFT_ALIGNMENT);

		String translators = i18n("translator(s)");
		int p = translators.indexOf("<html>");
		if (p >= 0)
			translators = translators.substring(p + 6);
		p = translators.indexOf("</html>");
		if (p >= 0)
			translators = translators.substring(0, p);

		String translationStr = "<table>"
			+ "<tr bgcolor=\"#A0A0FF\">"
			+ "<th align=\"left\">" + i18n("translation") + "</th></tr>"
			+ "<tr><td bgcolor=\"#C8FFC8\">"
			+ translators
			+ "</td></tr></table>";

		JEditorPane about = new JEditorPane("text/html",
			"<html>"
			+ "<h2 align=\"center\">" + Version.product + "</h2>"
			+ "<h3 align=\"center\">" + i18n("ADAClientOf") + "<br>"
			+ "<a href=\"" + Version.projectHome + "\">"
			+ "webCDwriter</a> - " + Version.subTitle + "</h3>"
//			+ i18n("version") + ": " + Version.version + "<br>"
//			+ i18n("author") + ": " + Version.author + "\n"
			+ "<h3 align=\"center\">" + Version.copyright + "<br>"
//			+ Version.eMail + "<br>"
			+ "<a href=\"" + Version.authorHome + "\">"
			+ Version.authorHome + "</a></h3>"
			+ translationStr
			+ "</html>");
		about.setEditable(false);
		about.addHyperlinkListener(
			new HyperlinkListener() {
				public void hyperlinkUpdate(HyperlinkEvent e) {
					if (e.getEventType()
						== HyperlinkEvent.EventType.ACTIVATED)
						CDcreator.showDocument(e.getURL());
				}
			}
		);
		tabbedPane.add(new JScrollPane(about), i18n("about"));

		JEditorPane systemPane = new JEditorPane("text/html",
			"<html>"
			+ i18n("system") + ": "
			+ System.getProperty("os.name") + " "
			+ System.getProperty("os.version")
			+ "<br><br>"
			+ "Java VM: " + CDcreator.vmName
			+ " " + CDcreator.vmVersion
			+ "<br><br>"
			+ i18n("user") + ": "
			+ System.getProperty("user.name")
			+ "</html>");
		systemPane.setEditable(false);
		tabbedPane.add(systemPane, i18n("system"));

		try {
			JEditorPane licensePane = new JEditorPane(
				CDcreator.getURL("gpl.html"));
			licensePane.setEditable(false);

			JScrollPane scroller = new JScrollPane();
			JViewport vp = scroller.getViewport();
			vp.add(licensePane);

			tabbedPane.add(scroller, i18n("ADLicense"));
		} catch (Exception e) {
			tabbedPane.add(new JEditorPane("text/html",
				"GNU GENERAL PUBLIC LICENSE<br>"
				+ "Version 2, June 1991"
				),
				i18n("ADLicense"));
		}

		panel.add(tabbedPane);

		JDialog d = new JOptionPane(
			panel, JOptionPane.INFORMATION_MESSAGE)
			.createDialog(this,
				i18n("about") + " " + Version.product + "...");
		d.setResizable(true);
		d.setVisible(true);
	}

	void showDebugInfo(String str) {
		Version.showDebugInfo(str);
	}

	void showFontInfo() {
		String
			slash = System.getProperty("file.separator"),
			javaHome = System.getProperty("java.home"),
			fontProperties = javaHome + slash + "lib" + slash
				+ "font.properties",
			msg = "The font \""
			+ new JButton().getFont().getFontName()
			+ "\" doesn´t support the locale "
			+ CDcreator.locale + ".\n"
			+ "Try to edit or replace the file "
			+ fontProperties + ".\n"
			+ "See " + Version.projectHome + "font.properties.html"
			+ " for details.";
		JOptionPane.showMessageDialog(this, msg, "Fonts",
			JOptionPane.ERROR_MESSAGE);
	}

	void transfer(TreePath treePath) throws Exception {
		showDebugInfo("transfer: " + treePath.toString());

		if (CDTree.isSelectionEmpty())
			CDTree.setSelectionRow(0);
		showDebugInfo("-> "
			+ CDTree.getSelectionPath().toString());

		File file = ((DirTreeNode)treePath
			.getLastPathComponent()).getFile();
		checkFile(file);
		CDNode newNode = new CDNode(file);
		TreePath CDPath = CDTree.getSelectionPath();
		DirTreeNode CDnode = (DirTreeNode)CDPath.getLastPathComponent();
		int p = CDTreeModel.getChildCount(CDnode);
		if (CDnode.isLeaf()) {
			p = CDTreeModel.getIndexOfChild(CDnode.getParent(), CDnode);
			CDnode = (DirTreeNode)CDnode.getParent();
		}
		if (CDnode == null || CDnode.isLeaf())
			return;
		for (int i = 0; i < p; i++) {
			if (CDTreeModel.getChild(CDnode, i).toString()
					.equals(newNode.toString()))
				return;
		}
		CDTreeModel.insertNodeInto(newNode, CDnode, p);
		Project.add(newNode, CDPath);
	}

	public boolean typeSelection(boolean canBeCancelled) {
		NewProjectDialog dialog = new NewProjectDialog(canBeCancelled);
		dialog.pack();
		center(dialog);
//		if (CDcreator.audioCDSupport)
		dialog.setVisible(true);
		if (canBeCancelled && dialog.wasCanceled())
			return false;
		updateCDRoot();
		return true;
	}

	private void updateCDRoot() {
		CDRoot.setUserObject(getCDTypeStr());
//		theCDView.updateUI();
//		CDTreeModel.nodeChanged(CDRoot);
		CDTreeModel.reload();
	}

	LayoutManager LM = new LayoutManager() {
		public void addLayoutComponent(String name, Component comp) {
			System.out.println("addLayoutComponent: " + name);
		}

		public void layoutContainer(Container parent) {
			Dimension d = parent.getSize();
			int xB = 5;
			int x = d.width - xB - xB - 60 - xB - xB;
			int y = d.height - 10 - 10;
			final int bs = 22 + 6;
			treeScroller.setBounds(
				xB, 10, x/2, y);
			copyButton.setBounds(
				xB + x/2 + xB, 10 + (y-20) / 2, 60, 30);
			burnButton.setBounds(
				xB + x/2 + xB + 12, 10 + 3 * (y-36) / 4 - 18, 36, 36);

			int mediumBoxHeight = mediumBox.getPreferredSize().height;
			mediumPanel.setBounds(
				xB + x/2 + xB + 60 + xB, 5, x/2, mediumBoxHeight);
			int y0 = 5 + mediumBoxHeight + 2;
			y = d.height - 2 * y0;
			CDTreeScroller.setBounds(
				xB + x/2 + xB + 60 + xB, y0, x/2, y);
			Rectangle bounds = new Rectangle(
				xB + x/2 + xB + 60 + xB - xB - bs, y0 + 5, bs, bs);
			removeButton.setBounds(bounds);
			bounds.translate(0, bs + 5);
			newDirButton.setBounds(bounds);
			bounds.translate(0, bs + 5);
			setBootImageButton.setBounds(bounds);

			bounds.y = y0 + y - 2 * (bs + 5);
			upButton.setBounds(bounds);
			bounds.translate(0, bs + 5);
			downButton.setBounds(bounds);
			sessionSizePanel.setBounds(
				xB + x/2 + xB + 60 + xB, y0 + y + 2,
				x/2, mediumBoxHeight);
		}

		public Dimension minimumLayoutSize(Container parent) {
			return new Dimension(100, 100);
		}

		public Dimension preferredLayoutSize(Container parent) {
			return new Dimension(400, 400);
		}

		public void removeLayoutComponent(Component comp) {
		}
	};

	TreeWillExpandListener treeWillExpandListener
		= new TreeWillExpandListener() {
		public void treeWillCollapse(TreeExpansionEvent event) {
		}
		public void treeWillExpand(TreeExpansionEvent event) {
			DirTreeNode CDnode = (DirTreeNode)
				event.getPath()
				.getLastPathComponent();
			CDnode.resetExpanded();
			((DefaultTreeModel)tree.getModel()).reload(CDnode);
		}
	};

	class MyTreeModelListener implements TreeModelListener {
		public void treeNodesChanged(TreeModelEvent e) {
			DirTreeNode node;
			node = (DirTreeNode)
				(e.getTreePath().getLastPathComponent());
			if (e.getChildIndices() != null) {
				int index = e.getChildIndices()[0];
				node = (DirTreeNode)
					(node.getChildAt(index));
			}
			System.out.println("New value: " + node);
		}
		public void treeNodesInserted(TreeModelEvent e) {
		}
		public void treeNodesRemoved(TreeModelEvent e) {
		}
		public void treeStructureChanged(TreeModelEvent e) {
		}
	}

	class MyTextField extends JTextField {
		protected void processKeyEvent(KeyEvent e) {
//			System.out.println(e.toString());
			if (e.getKeyCode() == KeyEvent.VK_ENTER) {
				Version.debug("cellEditor",
					"-> " + CDTree.getEditingPath());
				if (getText().equals("")) {
					JOptionPane.showMessageDialog(
						CDcreator.mainWin,
						i18n("MWEmptyFileName"),
						i18n("error"),
						JOptionPane.ERROR_MESSAGE);
				}
				else {
					Project.rename(CDTree.getEditingPath(), getText());
					super.processKeyEvent(e);
				}
			}
			else
				super.processKeyEvent(e);
		}
	}

//	private static Font font = new Font("Bitstream Cyberbit", 0, 12);

/*	class JMenu extends javax.swing.JMenu {
		JMenu(String s) {
			super(s);
			try {
				if (getFont().canDisplayUpTo(s) < s.length())
					if (font != null)
						setFont(font);
			} catch (NoSuchMethodError e) {}
		}
	}
*/
	class JMenuItem extends javax.swing.JMenuItem {
		JMenuItem(String s) {
			super(i18n(s));
			setActionCommand(s);
/*			try {
				String s2 = i18n(s);
				if (getFont().canDisplayUpTo(s2) < s2.length())
					if (font != null)
						setFont(font);
			} catch (NoSuchMethodError e) {}
*/		}
	}
}
