Package jreepad

Source Code of jreepad.JreepadViewer$SaveAction

/*
           Jreepad - personal information manager.
           Copyright (C) 2004 Dan Stowell

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.

The full license can be read online here:

           http://www.gnu.org/copyleft/gpl.html
*/


package jreepad;

import java.awt.Color;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
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.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ListIterator;
import java.util.ResourceBundle;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SpinnerNumberModel;
import javax.swing.UIManager;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;

import jreepad.io.AutoDetectReader;
import jreepad.io.EncryptedWriter;
import jreepad.io.HtmlWriter;
import jreepad.io.JreepadReader;
import jreepad.io.JreepadWriter;
import jreepad.io.TreepadWriter;
import jreepad.io.XmlWriter;
import jreepad.ui.PasswordDialog;
import jreepad.ui.SaveFileChooser;
import edu.stanford.ejalbert.BrowserLauncher;
import edu.stanford.ejalbert.exception.BrowserLaunchingExecutionException;
import edu.stanford.ejalbert.exception.BrowserLaunchingInitializingException;
import edu.stanford.ejalbert.exception.UnsupportedOperatingSystemException;
import jreepad.ui.FontHelper;

public class JreepadViewer
    extends JFrame { // implements ApplicationListener
  // Jreepad version, to appear in "about" box etc
  public static String version = "1.6 rc1";

  private static Vector theApps = new Vector(1,1);
  private Box toolBar, toolBarIconic;
  private JreepadView theJreepad;
  private JreepadTreeModel document;
  private Container content;
// DEPRECATED  private File prefsFile = new File(System.getProperty("user.home"), ".jreepref");
  protected static ResourceBundle lang = ResourceBundle.getBundle("jreepad.lang.JreepadStrings");

//  private static final String[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(null);
//  private static final String[] fontSizes = new String[] {"8","9","10","11","12","13","14","16","18","20","24","30","36"};

  private JFileChooser fileChooser;

  private String windowTitle;

  protected Clipboard systemClipboard;

  private JButton addAboveButton;
  private JButton addBelowButton;
  private JButton addButton;
  private JButton removeButton;
  private JButton upButton;
  private JButton downButton;
  private JButton indentButton;
  private JButton outdentButton;
  private JComboBox viewSelector, viewSelectorIconic;

  private JButton newIconButton;
  private JButton openIconButton;
  private JButton addAboveIconButton;
  private JButton addBelowIconButton;
  private JButton addIconButton;
  private JButton removeIconButton;
  private JButton upIconButton;
  private JButton downIconButton;
  private JButton indentIconButton;
  private JButton outdentIconButton;

  private Thread autoSaveThread;

  private JDialog autoSaveDialog;
  private JCheckBox autoSaveCheckBox;
  private JSpinner autoSavePeriodSpinner;
//  private DSpinner autoSavePeriodSpinner;
  private JButton autoSaveOkButton;
  private JButton autoSaveCancelButton;

  private JDialog prefsDialog;
  private SearchDialog searchDialog;

  private JDialog nodeUrlDisplayDialog;
  private JTextField nodeUrlDisplayField;
  private JButton nodeUrlDisplayOkButton;


    private JMenu openRecentMenu;
  private JMenuItem undoMenuItem;
  private JMenuItem redoMenuItem;
  private JMenuItem webSearchMenuItem;
  private JMenuItem characterWrapArticleMenuItem;
    private JCheckBoxMenuItem viewToolbarIconsMenuItem;
    private JCheckBoxMenuItem viewToolbarTextMenuItem;
    private JCheckBoxMenuItem viewToolbarOffMenuItem;

  private ColouredStrip funkyGreenStrip;

  // private boolean htmlExportOkChecker = false; // Just used to check whether OK or Cancel has been pressed in a certain dialogue box

  // Check whether we are on Mac OS X.  This is crucial to loading and using the OSXAdapter class.
  public static boolean MAC_OS_X = (System.getProperty("os.name").toLowerCase().startsWith("mac os x"));

  // Ask AWT which menu modifier we should be using.
  final static int MENU_MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();

  /*
  Note - The application code registered with Apple is:
  JREE� (Hex) 4A524545

  In Apple's Java methods they require an integer, so
  presumably we use 0x4A524545
  */
  public static final int appleAppCode = 0x4A524545;

  public JreepadViewer()
  {
    this("");
  }
  public JreepadViewer(String fileNameToLoad)
  {
    this(fileNameToLoad, null);
  }
  public JreepadViewer(String fileNameToLoad, String prefFilename)
  {
// THIS DOESN'T SEEM TO HAVE ANY EFFECT, ON MAC OSX - I'd be interested to know if it does its job on other OSs
// Apparently it does work on Windows. So I'll leave it in place!
    ClassLoader loader = this.getClass().getClassLoader(); // Used for loading icon
    java.net.URL iconUrl = loader.getResource("images/jreepadlogo-01-iconsize.gif");
    if(iconUrl != null){
      setIconImage(new ImageIcon(iconUrl).getImage());
    }else{
      System.out.println("Icon image failed to load: images/jreepadlogo-01-iconsize.gif");
    }

    Toolkit theToolkit = getToolkit();
    Dimension wndSize = theToolkit.getScreenSize();
    systemClipboard = theToolkit.getSystemClipboard();

    // New method of loading prefs - using java's own API rather handling a file
    setPrefs(new JreepadPrefs(wndSize));
    if(!getPrefs().seenLicense) {
      showLicense();
      getPrefs().seenLicense = true;
    }
/*
    // Check if a preferences file exists - and if so, load it
    if(prefFilename!=null)
      prefsFile = new File(prefFilename);
    try
    {
      if(prefsFile.exists() && prefsFile.isFile())
      {
        ObjectInputStream prefsLoader = new ObjectInputStream(new FileInputStream(prefsFile));
        setPrefs((JreepadPrefs)prefsLoader.readObject());
        prefsLoader.close();
      }
      else
      {
        showLicense(); // A crude way of showing the license on first visit
        setPrefs(new JreepadPrefs(wndSize));
      }
    }
    catch(Exception err)
    {
      setPrefs(new JreepadPrefs(wndSize));
    }
*/

    fileChooser = new JFileChooser();
    fileChooser.addChoosableFileFilter(SaveFileChooser.JREEPAD_FILE_FILTER);
    fileChooser.addChoosableFileFilter(SaveFileChooser.JREEPAD_ENCRYPTED_FILE_FILTER);
    fileChooser.addChoosableFileFilter(SaveFileChooser.TREEPAD_FILE_FILTER);

    content = getContentPane();

    document = new JreepadTreeModel();
    theJreepad = new JreepadView(document);

    establishMenus();
    establishToolbar();
    searchDialog = new SearchDialog(this, theJreepad);
    prefsDialog = new PrefsDialog(this);
    establishAutosaveDialogue();
    establishNodeUrlDisplayDialogue();

    // Establish the autosave thread
    autoSaveThread = new Thread("Autosave thread")
                        {
                          public void run()
                          {
                            while(getPrefs().autoSave)
                            {
                              try
                              {
                                // Sleep for a bit...
                                sleep(60000L * getPrefs().autoSavePeriod);
                                yield();
                                // ...then if the saveLocation != null, trigger saveAction()
                                if(getPrefs().autoSave && document.getSaveLocation() != null)
                                  new SaveAction().actionPerformed(null);
                                else
                                  updateWindowTitle();
                              }
                              catch(InterruptedException e){}
                            }
                          }
                        };
    autoSaveThread.setPriority(Thread.MIN_PRIORITY);
    if(getPrefs().autoSave)
      autoSaveThread.start();
    // Finished establishing the autosave thread

    content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
    content.add(funkyGreenStrip = new ColouredStrip(new Color(0.09f, 0.4f, 0.12f), wndSize.width, 10) );
    funkyGreenStrip.setVisible(getPrefs().showGreenStrip);
    content.add(toolBar);
    content.add(toolBarIconic);
    setToolbarMode(getPrefs().toolbarMode);
    content.add(theJreepad);

    // Load the file - if it has been specified, and if it can be found, and if it's a valid HJT file
    File firstTimeFile = null;
    if(fileNameToLoad != "")
      firstTimeFile = new File(fileNameToLoad);
    else if(getPrefs().loadLastFileOnOpen && getPrefs().getMostRecentFile() != null)
      firstTimeFile = getPrefs().getMostRecentFile();

    if(firstTimeFile != null && firstTimeFile.isFile())
      openFile(firstTimeFile);

    // Set close operation
    setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
    addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e){ quitAction(); }});

    setTitleBasedOnFilename("");

    // Finally, make the window visible and well-sized
    setBounds(getPrefs().windowLeft,getPrefs().windowTop,
              getPrefs().windowWidth, getPrefs().windowHeight);
    searchDialog.setBounds(getPrefs().windowWidth/2,getPrefs().windowHeight/6,
              (int)(getPrefs().windowWidth*0.7f),(int)(getPrefs().windowHeight*0.9f));
    autoSaveDialog.setBounds((int)(wndSize.width*0.5f),getPrefs().windowHeight/2,
              getPrefs().windowWidth/2, getPrefs().windowHeight/4);
    prefsDialog.setBounds(getPrefs().windowWidth/2,getPrefs().windowHeight/3,
              getPrefs().windowWidth, getPrefs().windowHeight);
    nodeUrlDisplayDialog.setBounds((int)(wndSize.width*0.1f),(int)(getPrefs().windowHeight*0.7f),
              (int)(getPrefs().windowWidth*1.3f), getPrefs().windowHeight/3);

    // pack() actually deprecates some of the functionality of the setBounds() calls just above
    //  - but hopefully gives a better mixture of sizes set programmatically and by the OS
    searchDialog.pack();
    autoSaveDialog.pack();
    prefsDialog.pack();
    nodeUrlDisplayDialog.pack();

    theApps.add(this);
    macOSXRegistration();

    setVisible(true);
    // If loading the last-saved file, expand the nodes we last had open
    if(document.getSaveLocation() != null)
        theJreepad.expandPaths(getPrefs().treePathCollection.paths);

    theJreepad.returnFocusToTree();
  }

  // Used by the constructor
  private void establishMenus()
  {
    // Create the menu bar
    JMenuBar menuBar = new JMenuBar();

    // Add menus
    menuBar.add(createFileMenu());
    menuBar.add(createEditMenu());
    menuBar.add(createActionsMenu());
    menuBar.add(createViewMenu());
    menuBar.add(createOptionsMenu());
    menuBar.add(createHelpMenu());
    setJMenuBar(menuBar);
  }

  /**
   * Creates the File menu.
   */
  private JMenu createFileMenu()
  {
      JMenu fileMenu = new JMenu(lang.getString("MENU_FILE")); //"File");
      fileMenu.setMnemonic(KeyEvent.VK_F);

      JMenuItem newMenuItem = new JMenuItem(lang.getString("MENUITEM_NEW")); //"New");
      newMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { newAction();}});
      fileMenu.add(newMenuItem);

      JMenuItem openMenuItem = new JMenuItem(lang.getString("MENUITEM_OPEN")); //"Open");
      openMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {openAction();}});
      fileMenu.add(openMenuItem);

      openRecentMenu = new JMenu(lang.getString("MENUITEM_OPENRECENT")); //"Open recent");
      updateOpenRecentMenu();
      fileMenu.add(openRecentMenu);

      fileMenu.add(new SaveAction()); // Save
      fileMenu.add(new SaveAction(true)); // Save As

      JMenuItem backupToMenuItem = new JMenuItem(lang.getString("MENUITEM_BACKUPTO")); //"Backup to...");
      backupToMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {backupToAction();}});
      fileMenu.add(backupToMenuItem);

      fileMenu.add(new JSeparator());

      JMenuItem printSubtreeMenuItem = new JMenuItem(lang.getString("MENUITEM_PRINTSUBTREE")); //"Print subtree");
      printSubtreeMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {subtreeToBrowserForPrintAction();}});
      fileMenu.add(printSubtreeMenuItem);

      JMenuItem printArticleMenuItem = new JMenuItem(lang.getString("MENUITEM_PRINTARTICLE")); //"Print article");
      printArticleMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {articleToBrowserForPrintAction();}});
      fileMenu.add(printArticleMenuItem);

      fileMenu.add(new JSeparator());
      JMenu importMenu = new JMenu(lang.getString("MENUITEM_IMPORT")); //"Import...");
      fileMenu.add(importMenu);

      JMenuItem importHjtMenuItem = new JMenuItem(lang.getString("MENUITEM_IMPORT_HJT")); //"...Treepad file as subtree");
      importHjtMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {importAction(FILE_FORMAT_HJT);}});
      importMenu.add(importHjtMenuItem);

      JMenuItem importTextMenuItem = new JMenuItem(lang.getString("MENUITEM_IMPORT_TEXTFILES")); //"...text file(s) as child node(s)");
      importTextMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {importAction(FILE_FORMAT_TEXT);}});
      importMenu.add(importTextMenuItem);

      JMenuItem importTextAsListMenuItem = new JMenuItem(lang.getString("MENUITEM_IMPORT_TEXTLIST")); //"...text list file, one-child-per-line");
      importTextAsListMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {importAction(FILE_FORMAT_TEXTASLIST);}});
      importMenu.add(importTextAsListMenuItem);

      fileMenu.add(createExportMenu());

      fileMenu.add(new JSeparator());
      if(!MAC_OS_X)
      {
          JMenuItem quitMenuItem = new JMenuItem(lang.getString("MENUITEM_QUIT")); //"Quit");
          quitMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { quitAction(); }});
          fileMenu.add(quitMenuItem);
          quitMenuItem.setMnemonic('Q');
          quitMenuItem.setAccelerator(KeyStroke.getKeyStroke('Q', MENU_MASK));
      }

      newMenuItem.setMnemonic('N');
      newMenuItem.setAccelerator(KeyStroke.getKeyStroke('N', MENU_MASK));
      openMenuItem.setMnemonic('O');
      openMenuItem.setAccelerator(KeyStroke.getKeyStroke('O', MENU_MASK));
      openRecentMenu.setMnemonic('R');
      printSubtreeMenuItem.setMnemonic('P');
      printSubtreeMenuItem.setAccelerator(KeyStroke.getKeyStroke('P', MENU_MASK));
      printArticleMenuItem.setAccelerator(KeyStroke.getKeyStroke('P', MENU_MASK | java.awt.Event.SHIFT_MASK));
      backupToMenuItem.setMnemonic('B');
      importMenu.setMnemonic('I');
      importHjtMenuItem.setMnemonic('f');
      importTextMenuItem.setMnemonic('t');
      importTextAsListMenuItem.setMnemonic('l');

      return fileMenu;
  }

  /**
   * Creates the Export submenu.
   */
  private JMenu createExportMenu()
  {
      JMenu exportMenu = new JMenu(lang.getString("MENUITEM_EXPORT")); //"Export selected...");

      JMenuItem exportHjtMenuItem = new JMenuItem(lang.getString("MENUITEM_EXPORT_HJT")); //"...subtree to Treepad HJT file");
      exportHjtMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {exportAction(FILE_FORMAT_HJT);}});
      exportMenu.add(exportHjtMenuItem);

      JMenuItem exportHtmlMenuItem = new JMenuItem(lang.getString("MENUITEM_EXPORT_HTML")); //"...subtree to HTML");
      exportHtmlMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {exportAction(FILE_FORMAT_HTML);}});
      exportMenu.add(exportHtmlMenuItem);

      JMenuItem exportSimpleXmlMenuItem = new JMenuItem(lang.getString("MENUITEM_EXPORT_XML")); //"...subtree to XML");
      exportSimpleXmlMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {exportAction(FILE_FORMAT_XML);}});
      exportMenu.add(exportSimpleXmlMenuItem);

      JMenuItem exportListMenuItem = new JMenuItem(lang.getString("MENUITEM_EXPORT_TEXTLIST")); //"...subtree to text list (node titles only)");
      exportListMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {exportAction(FILE_FORMAT_TEXTASLIST);}});
      exportMenu.add(exportListMenuItem);

      exportMenu.add(new JSeparator());

      JMenuItem exportTextMenuItem = new JMenuItem(lang.getString("MENUITEM_EXPORT_ARTICLE")); //"...article to text file");
      exportTextMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {exportAction(FILE_FORMAT_TEXT);}});
      exportMenu.add(exportTextMenuItem);

      JMenuItem exportSubtreeTextMenuItem = new JMenuItem(lang.getString("MENUITEM_EXPORT_ARTICLES")); //"...subtree articles to text file");
      exportSubtreeTextMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {exportAction(FILE_FORMAT_ARTICLESTOTEXT);}});
      exportMenu.add(exportSubtreeTextMenuItem);

      exportMenu.setMnemonic('E');
      exportHjtMenuItem.setMnemonic('f');
      exportHtmlMenuItem.setMnemonic('h');
      exportSimpleXmlMenuItem.setMnemonic('x');
      exportTextMenuItem.setMnemonic('t');

      return exportMenu;
  }

  /**
   * Creates the Edit menu.
   */
  private JMenu createEditMenu()
  {
      JMenu editMenu = new JMenu(lang.getString("MENU_EDIT")); //"Edit");
      editMenu.setMnemonic(KeyEvent.VK_E);

      undoMenuItem = new JMenuItem(lang.getString("MENUITEM_UNDO")); //"Undo");
      undoMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {
          undoAction();
          updateUndoRedoMenuState();}});
      editMenu.add(undoMenuItem);

      redoMenuItem = new JMenuItem(lang.getString("MENUITEM_REDO")); //"Redo");
      redoMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {
          redoAction();
          updateUndoRedoMenuState();}});
      editMenu.add(redoMenuItem);

      editMenu.add(new JSeparator());

      JMenuItem addAboveMenuItem = new JMenuItem(lang.getString("MENUITEM_ADDABOVE")); //"Add sibling above");
      addAboveMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { theJreepad.addNodeAbove(); updateWindowTitle();}});
      editMenu.add(addAboveMenuItem);

      JMenuItem addBelowMenuItem = new JMenuItem(lang.getString("MENUITEM_ADDBELOW")); //"Add sibling below");
      addBelowMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { theJreepad.addNodeBelow(); updateWindowTitle();}});
      editMenu.add(addBelowMenuItem);

      JMenuItem addChildMenuItem = new JMenuItem(lang.getString("MENUITEM_ADDCHILD")); //"Add child");
      addChildMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { theJreepad.addNode(); updateWindowTitle(); }});
      editMenu.add(addChildMenuItem);

      editMenu.add(new JSeparator());

      JMenuItem newFromClipboardMenuItem = new JMenuItem(lang.getString("MENUITEM_NEWFROMCLIPBOARD")); //"New node from clipboard");
      newFromClipboardMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { systemClipboardToNewNode(); }});
      editMenu.add(newFromClipboardMenuItem);

      editMenu.add(new JSeparator());

      JMenuItem editNodeTitleMenuItem = new JMenuItem(lang.getString("MENUITEM_EDITNODETITLE")); //"Edit node title");
      editNodeTitleMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { theJreepad.editNodeTitleAction(); }});
      editMenu.add(editNodeTitleMenuItem);

      editMenu.add(new JSeparator());

      JMenuItem deleteMenuItem = new JMenuItem(lang.getString("MENUITEM_DELETENODE")); //"Delete node");
      deleteMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { deleteNodeAction(); }});
      editMenu.add(deleteMenuItem);

      editMenu.add(new JSeparator());

      JMenuItem upMenuItem = new JMenuItem(lang.getString("MENUITEM_MOVEUP")); //"Move node up");
      upMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { theJreepad.moveCurrentNodeUp(); theJreepad.returnFocusToTree(); updateWindowTitle(); }});
      editMenu.add(upMenuItem);

      JMenuItem downMenuItem = new JMenuItem(lang.getString("MENUITEM_MOVEDOWN")); //"Move node down");
      downMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { theJreepad.moveCurrentNodeDown(); theJreepad.returnFocusToTree(); updateWindowTitle(); }});
      editMenu.add(downMenuItem);

      editMenu.add(new JSeparator());

      JMenuItem indentMenuItem = new JMenuItem(lang.getString("MENUITEM_MOVEIN")); //"Indent node (demote)");
      indentMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { theJreepad.indentCurrentNode(); theJreepad.returnFocusToTree(); updateWindowTitle(); }});
      editMenu.add(indentMenuItem);

      JMenuItem outdentMenuItem = new JMenuItem(lang.getString("MENUITEM_MOVEOUT")); //"Outdent node (promote)");
      outdentMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { theJreepad.outdentCurrentNode(); theJreepad.returnFocusToTree(); updateWindowTitle(); }});
      editMenu.add(outdentMenuItem);

      editMenu.add(new JSeparator());

      JMenuItem expandAllMenuItem = new JMenuItem(lang.getString("MENUITEM_EXPAND")); //"Expand subtree");
      expandAllMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { theJreepad.expandAllCurrentNode(); }});
      editMenu.add(expandAllMenuItem);

      JMenuItem collapseAllMenuItem = new JMenuItem(lang.getString("MENUITEM_COLLAPSE")); //"Collapse subtree");
      collapseAllMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { theJreepad.collapseAllCurrentNode(); }});
      editMenu.add(collapseAllMenuItem);

      undoMenuItem.setMnemonic('u');
      undoMenuItem.setAccelerator(KeyStroke.getKeyStroke('Z', MENU_MASK));
      redoMenuItem.setMnemonic('r');
      redoMenuItem.setAccelerator(KeyStroke.getKeyStroke('Z', MENU_MASK | java.awt.event.InputEvent.SHIFT_MASK));
      addAboveMenuItem.setMnemonic('a');
      addAboveMenuItem.setAccelerator(KeyStroke.getKeyStroke('T', MENU_MASK));
      addBelowMenuItem.setMnemonic('b');
      addBelowMenuItem.setAccelerator(KeyStroke.getKeyStroke('B', MENU_MASK));
      addChildMenuItem.setMnemonic('c');
      addChildMenuItem.setAccelerator(KeyStroke.getKeyStroke('D', MENU_MASK));
      newFromClipboardMenuItem.setAccelerator(KeyStroke.getKeyStroke('M', MENU_MASK));
      editNodeTitleMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0));
      upMenuItem.setMnemonic('u');
      upMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_UP, MENU_MASK | java.awt.Event.ALT_MASK));
      downMenuItem.setMnemonic('d');
      downMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, MENU_MASK | java.awt.Event.ALT_MASK));
      indentMenuItem.setMnemonic('i');
      indentMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, MENU_MASK | java.awt.Event.ALT_MASK));
      outdentMenuItem.setMnemonic('o');
      outdentMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, MENU_MASK | java.awt.Event.ALT_MASK));
      expandAllMenuItem.setMnemonic('x');
      expandAllMenuItem.setAccelerator(KeyStroke.getKeyStroke('=', MENU_MASK));
      collapseAllMenuItem.setMnemonic('l');
      collapseAllMenuItem.setAccelerator(KeyStroke.getKeyStroke('-', MENU_MASK));
      deleteMenuItem.setMnemonic('k');
      deleteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, MENU_MASK));

      undoMenuItem.setMnemonic('u');
      undoMenuItem.setAccelerator(KeyStroke.getKeyStroke('Z', MENU_MASK));
      redoMenuItem.setMnemonic('r');
      redoMenuItem.setAccelerator(KeyStroke.getKeyStroke('Z', MENU_MASK | java.awt.event.InputEvent.SHIFT_MASK));
      addAboveMenuItem.setMnemonic('a');
      addAboveMenuItem.setAccelerator(KeyStroke.getKeyStroke('T', MENU_MASK));
      addBelowMenuItem.setMnemonic('b');
      addBelowMenuItem.setAccelerator(KeyStroke.getKeyStroke('B', MENU_MASK));
      addChildMenuItem.setMnemonic('c');
      addChildMenuItem.setAccelerator(KeyStroke.getKeyStroke('D', MENU_MASK));
      newFromClipboardMenuItem.setAccelerator(KeyStroke.getKeyStroke('M', MENU_MASK));
      upMenuItem.setMnemonic('u');
      upMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_UP, MENU_MASK | java.awt.Event.ALT_MASK));
      downMenuItem.setMnemonic('d');
      downMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, MENU_MASK | java.awt.Event.ALT_MASK));
      indentMenuItem.setMnemonic('i');
      indentMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, MENU_MASK | java.awt.Event.ALT_MASK));
      outdentMenuItem.setMnemonic('o');
      outdentMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, MENU_MASK | java.awt.Event.ALT_MASK));
      expandAllMenuItem.setMnemonic('x');
      expandAllMenuItem.setAccelerator(KeyStroke.getKeyStroke('=', MENU_MASK));
      collapseAllMenuItem.setMnemonic('l');
      collapseAllMenuItem.setAccelerator(KeyStroke.getKeyStroke('-', MENU_MASK));
      deleteMenuItem.setMnemonic('k');
      deleteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, MENU_MASK));

      return editMenu;
  }

  /**
   * Creates the Actions menu.
   */
  private JMenu createActionsMenu()
  {
    JMenu actionsMenu = new JMenu(lang.getString("MENU_ACTIONS")); // "Actions");
    actionsMenu.setMnemonic(KeyEvent.VK_T);

    JMenuItem searchMenuItem = new JMenuItem(lang.getString("MENUITEM_SEARCH")); //"Search");
    searchMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { searchDialog.open(); }});
    actionsMenu.add(searchMenuItem);

    JMenuItem launchUrlMenuItem = new JMenuItem(lang.getString("MENUITEM_FOLLOWLINK")); //"Follow highlighted link");
    launchUrlMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { theJreepad.openURLSelectedInArticle(); }});
    actionsMenu.add(launchUrlMenuItem);

    webSearchMenuItem = new JMenuItem(getPrefs().webSearchName);
    webSearchMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { theJreepad.webSearchTextSelectedInArticle(); }});
    actionsMenu.add(webSearchMenuItem);

    actionsMenu.add(new JSeparator());

    characterWrapArticleMenuItem = new JMenuItem(lang.getString("MENUITEM_HARDWRAP1") + " " + getPrefs().characterWrapWidth + " " + lang.getString("MENUITEM_HARDWRAP2")); //);
    characterWrapArticleMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { wrapContentToCharWidth(); }});
    actionsMenu.add(characterWrapArticleMenuItem);

    JMenuItem stripTagsMenuItem = new JMenuItem(lang.getString("MENUITEM_STRIPTAGS")); //"Strip <tags> from article");
    stripTagsMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { stripAllTags(); }});
    actionsMenu.add(stripTagsMenuItem);

    JMenuItem insertDateMenuItem = new JMenuItem(lang.getString("MENUITEM_INSERTDATE")); //"Insert date");
    insertDateMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { insertDate(); }});
    actionsMenu.add(insertDateMenuItem);

    actionsMenu.add(new JSeparator());

    JMenuItem sortMenuItem = new JMenuItem(lang.getString("MENUITEM_SORTONELEVEL")); //"Sort children (one level)");
    sortMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { theJreepad.sortChildren(); updateWindowTitle(); }});
    actionsMenu.add(sortMenuItem);

    JMenuItem sortRecursiveMenuItem = new JMenuItem(lang.getString("MENUITEM_SORTALLLEVELS")); //"Sort children (all levels)");
    sortRecursiveMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { theJreepad.sortChildrenRecursive(); updateWindowTitle(); }});
    actionsMenu.add(sortRecursiveMenuItem);

    searchMenuItem.setMnemonic('s');
    searchMenuItem.setAccelerator(KeyStroke.getKeyStroke('F', MENU_MASK));
    webSearchMenuItem.setMnemonic('g');
    webSearchMenuItem.setAccelerator(KeyStroke.getKeyStroke('G', MENU_MASK));
    characterWrapArticleMenuItem.setAccelerator(KeyStroke.getKeyStroke('R', MENU_MASK));
    characterWrapArticleMenuItem.setMnemonic('r');
    launchUrlMenuItem.setAccelerator(KeyStroke.getKeyStroke('L', MENU_MASK));
    launchUrlMenuItem.setMnemonic('l');
    stripTagsMenuItem.setAccelerator(KeyStroke.getKeyStroke('T', MENU_MASK));
    stripTagsMenuItem.setMnemonic('t');
    insertDateMenuItem.setAccelerator(KeyStroke.getKeyStroke('E', MENU_MASK));
    insertDateMenuItem.setMnemonic('e');

    return actionsMenu;
  }

  /**
   * Creates the View menu.
   */
  private JMenu createViewMenu()
  {
    JMenu viewMenu = new JMenu(lang.getString("MENU_VIEW")); //"View");
    viewMenu.setMnemonic('V');

    JMenuItem viewBothMenuItem = new JMenuItem(lang.getString("MENUITEM_VIEWBOTH")); //"Both tree and article");
    viewBothMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { setViewMode(JreepadPrefs.VIEW_BOTH); }});
    viewMenu.add(viewBothMenuItem);
    JMenuItem viewTreeMenuItem = new JMenuItem(lang.getString("MENUITEM_VIEWTREE")); //"Tree");
    viewTreeMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { setViewMode(JreepadPrefs.VIEW_TREE); }});
    viewMenu.add(viewTreeMenuItem);
    JMenuItem viewArticleMenuItem = new JMenuItem(lang.getString("MENUITEM_VIEWARTICLE")); //"Article");
    viewArticleMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { setViewMode(JreepadPrefs.VIEW_ARTICLE); }});
    viewMenu.add(viewArticleMenuItem);
    viewMenu.add(new JSeparator());

    JMenu viewToolbarMenu = new JMenu(lang.getString("MENUITEM_TOOLBAR")); //"Toolbar");
    viewMenu.add(viewToolbarMenu);
      viewToolbarIconsMenuItem = new JCheckBoxMenuItem(lang.getString("MENUITEM_TOOLBAR_ICONS")); //"Icons", true);
      viewToolbarIconsMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {
                                                  setToolbarMode(JreepadPrefs.TOOLBAR_ICON);
                                                  }});
      viewToolbarMenu.add(viewToolbarIconsMenuItem);
      viewToolbarTextMenuItem = new JCheckBoxMenuItem(lang.getString("MENUITEM_TOOLBAR_TEXT")); //"Text", true);
      viewToolbarTextMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {
                                                  setToolbarMode(JreepadPrefs.TOOLBAR_TEXT);
                                                  }});
      viewToolbarMenu.add(viewToolbarTextMenuItem);
      viewToolbarOffMenuItem = new JCheckBoxMenuItem(lang.getString("MENUITEM_TOOLBAR_OFF")); //"Off", true);
      viewToolbarOffMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {
                                                  setToolbarMode(JreepadPrefs.TOOLBAR_OFF);
                                                  }});
      viewToolbarMenu.add(viewToolbarOffMenuItem);



    viewMenu.add(new JSeparator());

    JMenuItem articleViewModeMenuItem = new JMenu(lang.getString("MENUITEM_ARTICLEFORMAT")); //"View this article as...");
    JMenuItem articleViewModeTextMenuItem = new JMenuItem(lang.getString("MENUITEM_ARTICLEFORMAT_TEXT")); //"Text");
      articleViewModeTextMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {
                theJreepad.setArticleMode(JreepadArticle.ARTICLEMODE_ORDINARY);
                updateUndoRedoMenuState();
                       }});
      articleViewModeMenuItem.add(articleViewModeTextMenuItem);
      JMenuItem articleViewModeHtmlMenuItem = new JMenuItem(lang.getString("MENUITEM_ARTICLEFORMAT_HTML")); //"HTML");
      articleViewModeHtmlMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {
                theJreepad.setArticleMode(JreepadArticle.ARTICLEMODE_HTML);
                updateUndoRedoMenuState();
                       }});
      articleViewModeMenuItem.add(articleViewModeHtmlMenuItem);
      JMenuItem articleViewModeCsvMenuItem = new JMenuItem(lang.getString("MENUITEM_ARTICLEFORMAT_CSV")); //"Table (comma-separated data)");
      articleViewModeCsvMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {
                theJreepad.setArticleMode(JreepadArticle.ARTICLEMODE_CSV);
                updateUndoRedoMenuState();
                       }});
      articleViewModeMenuItem.add(articleViewModeCsvMenuItem);
      JMenuItem articleViewModeTextileMenuItem = new JMenuItem(lang.getString("MENUITEM_ARTICLEFORMAT_TEXTILE"));
      articleViewModeTextileMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {
                theJreepad.setArticleMode(JreepadArticle.ARTICLEMODE_TEXTILEHTML);
                updateUndoRedoMenuState();
                       }});
      articleViewModeMenuItem.add(articleViewModeTextileMenuItem);
    viewMenu.add(articleViewModeMenuItem);


    viewMenu.add(new JSeparator());
    JMenuItem thisNodesUrlMenuItem = new JMenuItem(lang.getString("MENUITEM_NODEADDRESS")); //"\"node://\" address for current node");
    thisNodesUrlMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { getTreepadNodeUrl(); }});
    viewMenu.add(thisNodesUrlMenuItem);

    thisNodesUrlMenuItem.setMnemonic('n');
    viewBothMenuItem.setMnemonic('b');
    viewTreeMenuItem.setMnemonic('t');
    viewArticleMenuItem.setMnemonic('a');
    viewBothMenuItem.setAccelerator(KeyStroke.getKeyStroke('1', MENU_MASK));
    viewTreeMenuItem.setAccelerator(KeyStroke.getKeyStroke('2', MENU_MASK));
    viewArticleMenuItem.setAccelerator(KeyStroke.getKeyStroke('3', MENU_MASK));
    viewToolbarIconsMenuItem.setAccelerator(KeyStroke.getKeyStroke('4', MENU_MASK));
    viewToolbarTextMenuItem.setAccelerator(KeyStroke.getKeyStroke('5', MENU_MASK));
    viewToolbarOffMenuItem.setAccelerator(KeyStroke.getKeyStroke('6', MENU_MASK));
    articleViewModeTextMenuItem.setAccelerator(KeyStroke.getKeyStroke('7', MENU_MASK));
    articleViewModeHtmlMenuItem.setAccelerator(KeyStroke.getKeyStroke('8', MENU_MASK));
    articleViewModeCsvMenuItem.setAccelerator(KeyStroke.getKeyStroke('9', MENU_MASK));
    articleViewModeTextileMenuItem.setAccelerator(KeyStroke.getKeyStroke('0', MENU_MASK));
    viewToolbarMenu.setMnemonic('o');

    viewMenu.add(new JSeparator());
    // section to adjust fonts
    JMenu articleFontMenu = new JMenu(lang.getString("MENUITEM_FONT_ARTICLE"));
    viewMenu.add(articleFontMenu);
    JMenuItem increaseFontMenuItem = new JMenuItem(lang.getString(
        "MENUITEM_FONT_INCREASE"));
    increaseFontMenuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        theJreepad.changeFont(FontHelper.FONT_DIR_UP, JreepadView.CHANGE_ARTICLE_FONT);
      }
    });
    JMenuItem decreaseFontMenuItem = new JMenuItem(lang.getString(
        "MENUITEM_FONT_DECREASE"));
    decreaseFontMenuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        theJreepad.changeFont(FontHelper.FONT_DIR_DOWN, JreepadView.CHANGE_ARTICLE_FONT);
      }
    });
    articleFontMenu.add(increaseFontMenuItem);
    articleFontMenu.add(decreaseFontMenuItem);

    JMenu treeFontMenu = new JMenu(lang.getString("MENUITEM_FONT_TREE"));
    viewMenu.add(treeFontMenu);
    JMenuItem increaseTreeFontMenuItem = new JMenuItem(lang.getString(
        "MENUITEM_FONT_INCREASE"));
    increaseTreeFontMenuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        theJreepad.changeFont(FontHelper.FONT_DIR_UP, JreepadView.CHANGE_TREE_FONT);
      }
    });
    JMenuItem decreaseTreeFontMenuItem = new JMenuItem(lang.getString(
        "MENUITEM_FONT_DECREASE"));
    decreaseTreeFontMenuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        theJreepad.changeFont(FontHelper.FONT_DIR_DOWN, JreepadView.CHANGE_TREE_FONT);
      }
    });
    treeFontMenu.add(increaseTreeFontMenuItem);
    treeFontMenu.add(decreaseTreeFontMenuItem);

    return viewMenu;
  }

  /**
   * Creates the Options menu.
   */
  private JMenu createOptionsMenu()
  {
      JMenu optionsMenu = new JMenu(lang.getString("MENU_OPTIONS")); //"Options");
      optionsMenu.setMnemonic('O');

      JMenuItem autoSaveMenuItem = new JMenuItem(lang.getString("MENUITEM_AUTOSAVE_PREFS")); //"Autosave...");
      autoSaveMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) { showAutoSaveDialog(); }});
      optionsMenu.add(autoSaveMenuItem);
      JMenuItem prefsMenuItem = new JMenuItem(lang.getString("MENUITEM_PREFS")); //"Preferences");
      prefsMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {
                                              // updateFontsInPrefsBox();
                                              showPrefsDialog(); }});
      optionsMenu.add(prefsMenuItem);

      autoSaveMenuItem.setMnemonic('a');
      prefsMenuItem.setMnemonic('p');

      return optionsMenu;
  }

  private JMenu createHelpMenu()
  {
      JMenu helpMenu = new JMenu(lang.getString("MENU_HELP")); //"Help");
      helpMenu.setMnemonic('H');

      JMenuItem keyboardHelpMenuItem = new JMenuItem(lang.getString("MENUITEM_KEYBOARDSHORTCUTS")); //"Keyboard shortcuts");
      keyboardHelpMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e)
            { keyboardHelp();
            }});
      helpMenu.add(keyboardHelpMenuItem);
      JMenuItem linksHelpMenuItem = new JMenuItem(lang.getString("MENUITEM_LINKSHELP")); //"Help with links");
      linksHelpMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e)
            { linksHelp();
            }});
      helpMenu.add(linksHelpMenuItem);
      JMenuItem dragDropHelpMenuItem = new JMenuItem(lang.getString("MENUITEM_DRAGDROPHELP")); //"Help with drag-and-drop");
      dragDropHelpMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e)
            { dragDropHelp();
            }});
      helpMenu.add(dragDropHelpMenuItem);
      helpMenu.add(new JSeparator());
      if(!MAC_OS_X)
      {
        JMenuItem aboutMenuItem = new JMenuItem(lang.getString("MENUITEM_ABOUT")); //"About Jreepad");
        aboutMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e)
              {
                aboutAction();
              }});
        aboutMenuItem.setMnemonic('a');
        helpMenu.add(aboutMenuItem);
      }
      JMenuItem licenseMenuItem = new JMenuItem(lang.getString("MENUITEM_LICENSE")); //"License");
      licenseMenuItem.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e)
              {
                showLicense();
              }});
      helpMenu.add(licenseMenuItem);

      keyboardHelpMenuItem.setMnemonic('k');
      dragDropHelpMenuItem.setMnemonic('d');
      linksHelpMenuItem.setMnemonic('l');
      licenseMenuItem.setMnemonic('i');

      return helpMenu;
  }

  // Used by the constructor
  public void establishToolbar()
  {
    // Add the toolbar buttons
    toolBar = Box.createHorizontalBox();
    toolBarIconic = Box.createHorizontalBox();
    //
    addAboveButton = new JButton(lang.getString("TOOLBAR_ADDABOVE"));
    addBelowButton = new JButton(lang.getString("TOOLBAR_ADDBELOW"));
    addButton = new JButton(lang.getString("TOOLBAR_ADDCHILD"));
    removeButton = new JButton(lang.getString("TOOLBAR_DELETE"));
    //
    upButton = new JButton(lang.getString("TOOLBAR_UP"));
    downButton = new JButton(lang.getString("TOOLBAR_DOWN"));
    indentButton = new JButton(lang.getString("TOOLBAR_IN"));
    outdentButton = new JButton(lang.getString("TOOLBAR_OUT"));
    //
    // Now the mnemonics...
    addAboveButton.setMnemonic('a');
    addBelowButton.setMnemonic('b');
    addButton.setMnemonic('c');
    upButton.setMnemonic('u');
    downButton.setMnemonic('d');
    indentButton.setMnemonic('i');
    outdentButton.setMnemonic('o');
    removeButton.setMnemonic('k');
    //
    viewSelector = new JComboBox(new String[]{lang.getString("TOOLBAR_VIEWBOTH"),lang.getString("TOOLBAR_VIEWTREE"),lang.getString("TOOLBAR_VIEWARTICLE")});
    viewSelector.setEditable(false);
    viewSelector.setSelectedIndex(0);
    viewSelector.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){
                               switch(viewSelector.getSelectedIndex())
                               {
                                 case 1:
                                   setViewMode(JreepadPrefs.VIEW_TREE); break;
                                 case 2:
                                   setViewMode(JreepadPrefs.VIEW_ARTICLE); break;
                                 default:
                                   setViewMode(JreepadPrefs.VIEW_BOTH); break;
                               }
                               } });
    viewSelectorIconic = new JComboBox(new String[]{lang.getString("TOOLBAR_VIEWBOTH"),lang.getString("TOOLBAR_VIEWTREE"),lang.getString("TOOLBAR_VIEWARTICLE")});
    viewSelectorIconic.setEditable(false);
    viewSelectorIconic.setSelectedIndex(0);
    viewSelectorIconic.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){
                               switch(viewSelectorIconic.getSelectedIndex())
                               {
                                 case 1:
                                   setViewMode(JreepadPrefs.VIEW_TREE); break;
                                 case 2:
                                   setViewMode(JreepadPrefs.VIEW_ARTICLE); break;
                                 default:
                                   setViewMode(JreepadPrefs.VIEW_BOTH); break;
                               }
                               } });

    // Add the actions to the toolbar buttons
    upButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ theJreepad.moveCurrentNodeUp(); repaint();  theJreepad.returnFocusToTree(); updateWindowTitle();} });
    downButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ theJreepad.moveCurrentNodeDown(); repaint();  theJreepad.returnFocusToTree(); updateWindowTitle();} });


    indentButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ theJreepad.indentCurrentNode(); repaint();  theJreepad.returnFocusToTree(); updateWindowTitle();} });
    outdentButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ theJreepad.outdentCurrentNode(); repaint(); theJreepad.returnFocusToTree(); updateWindowTitle(); } });




    addAboveButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ theJreepad.addNodeAbove(); repaint(); updateWindowTitle();} });
    addBelowButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ theJreepad.addNodeBelow(); repaint(); updateWindowTitle();} });
    addButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ theJreepad.addNode(); repaint(); updateWindowTitle();} });
    removeButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ deleteNodeAction(); } });


    // Now establish the iconic buttons (code contributed by Coen Schalkwijk)
        // New file
        newIconButton = new JButton();
        newIconButton.setToolTipText(lang.getString("TOOLBAR_NEW"));
        newIconButton.setBorderPainted(false);
        newIconButton.setIcon(this.getIcon("New16.gif"));

        // Open existing
        openIconButton = new JButton();
        openIconButton.setToolTipText(lang.getString("TOOLBAR_OPEN"));
        openIconButton.setBorderPainted(false);
        openIconButton.setIcon(this.getIcon("Open16.gif"));

        // Save current
        JButton saveIconButton = new JButton(new SaveAction());
        saveIconButton.setBorderPainted(false);
        saveIconButton.setText(null); // Ignore action text

        // Insert node before
        addAboveIconButton = new JButton(lang.getString("TOOLBAR_ADDABOVE"));
//      addAboveIconButton = new JButton();
//      addAboveIconButton.setToolTipText(lang.getString("TOOLBAR_"));
//      addAboveIconButton.setBorderPainted(false);
//      addAboveIconButton.setMnemonic('a');
//      addAboveIconButton.setIcon(this.getIcon("InsertBefore16.gif"));

        // Insert node after
        addBelowIconButton = new JButton(lang.getString("TOOLBAR_ADDBELOW"));
//      addBelowIconButton = new JButton();
        addBelowIconButton.setMnemonic('b');
//      addBelowIconButton.setToolTipText("Add below");
//      addBelowIconButton.setBorderPainted(false);
//      addBelowIconButton.setIcon(this.getIcon("InsertAfter16.gif"));

        // Add child node
        addIconButton = new JButton();
        addIconButton.setMnemonic('c');
        addIconButton.setToolTipText(lang.getString("TOOLBAR_ADDCHILD"));
        addIconButton.setBorderPainted(false);
        addIconButton.setIcon(this.getIcon("Add16.gif"));

        // Remove node
        removeIconButton = new JButton();
        removeIconButton.setMnemonic('k');
        removeIconButton.setToolTipText(lang.getString("TOOLBAR_DELETE"));
        removeIconButton.setBorderPainted(false);
        removeIconButton.setIcon(this.getIcon("Remove16.gif"));

        // Move node up
        upIconButton = new JButton();
        upIconButton.setMnemonic('u');
        upIconButton.setToolTipText(lang.getString("TOOLBAR_UP"));
        upIconButton.setBorderPainted(false);
        upIconButton.setIcon(this.getIcon("Up16.gif"));

        // Move node down
        downIconButton = new JButton();
        downIconButton.setMnemonic('d');
        downIconButton.setToolTipText(lang.getString("TOOLBAR_DOWN"));
        downIconButton.setBorderPainted(false);
        downIconButton.setIcon(this.getIcon("Down16.gif"));

        // Move node from current
        outdentIconButton = new JButton();
        outdentIconButton.setMnemonic('i');
        outdentIconButton.setToolTipText(lang.getString("TOOLBAR_IN"));
        outdentIconButton.setBorderPainted(false);
        outdentIconButton.setIcon(this.getIcon("Back16.gif"));

        // Move node to previous
        indentIconButton = new JButton();
        indentIconButton.setMnemonic('o');
        indentIconButton.setToolTipText(lang.getString("TOOLBAR_OUT"));
        indentIconButton.setBorderPainted(false);
        indentIconButton.setIcon(this.getIcon("Forward16.gif"));

    // Add the actions to the toolbar buttons
    newIconButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ newAction(); } });
    openIconButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ openAction(); } });
    upIconButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ theJreepad.moveCurrentNodeUp(); repaint();
          theJreepad.returnFocusToTree();
          updateWindowTitle();} });
    downIconButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ theJreepad.moveCurrentNodeDown(); repaint();
          theJreepad.returnFocusToTree();
          updateWindowTitle();} });
    indentIconButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ theJreepad.indentCurrentNode(); repaint();
          theJreepad.returnFocusToTree();
          updateWindowTitle();} });
    outdentIconButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ theJreepad.outdentCurrentNode(); repaint();
          theJreepad.returnFocusToTree();
          updateWindowTitle(); } });
    addAboveIconButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ theJreepad.addNodeAbove(); repaint(); /*
          theJreepad.returnFocusToTree(); */
          updateWindowTitle();} });
    addBelowIconButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ theJreepad.addNodeBelow(); repaint(); /*
          theJreepad.returnFocusToTree(); */
          updateWindowTitle();} });
    addIconButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ theJreepad.addNode(); repaint(); /*
          theJreepad.returnFocusToTree(); */
          updateWindowTitle();} });
    removeIconButton.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){ deleteNodeAction(); } });
    // Finished establishing the iconic buttons




// Add all the buttons to their respective toolbar
    toolBar.add(addAboveButton);
    toolBar.add(addBelowButton);
    toolBar.add(addButton);
    toolBar.add(removeButton);
    toolBar.add(upButton);
    toolBar.add(downButton);
    toolBar.add(indentButton);
    toolBar.add(outdentButton);
    toolBar.add(viewSelector);
    toolBar.add(Box.createGlue());


    toolBarIconic.add(newIconButton);
    toolBarIconic.add(openIconButton);
    toolBarIconic.add(saveIconButton);
//  if(!MAC_OS_X) // The separators look RUBBISH on OSX
//    toolBarIconic.add(new JSeparator(JSeparator.VERTICAL));
//    toolBarIconic.add(Box.createHorizontalStrut(16));
    toolBarIconic.add(addAboveIconButton);
    toolBarIconic.add(addBelowIconButton);
    toolBarIconic.add(addIconButton);
    toolBarIconic.add(removeIconButton);
//  if(!MAC_OS_X) // The separators look RUBBISH on OSX
//    toolBarIconic.add(new JSeparator(JSeparator.VERTICAL));
//    toolBarIconic.add(Box.createHorizontalStrut(16));
    toolBarIconic.add(upIconButton);
    toolBarIconic.add(downIconButton);
    toolBarIconic.add(outdentIconButton);
    toolBarIconic.add(indentIconButton);
//  if(!MAC_OS_X) // The separators look RUBBISH on OSX
//    toolBarIconic.add(new JSeparator(JSeparator.VERTICAL));
//    toolBarIconic.add(Box.createHorizontalStrut(16));
    toolBarIconic.add(viewSelectorIconic);
    toolBarIconic.add(Box.createGlue());
  }


  private ClassLoader loader = this.getClass().getClassLoader();
  private final Icon getIcon(String name){
    try{
       // TODO create single funct for all img loading
       URL iconUrl = loader.getResource("images/"+name);
         return new ImageIcon(iconUrl);
       }catch(Exception e){
         System.err.println("Jreepad: Icon image failed to load: images/"+name);
         // e.printStackTrace();// Ignore, use default icon
       }
     return null;
  }



  protected void setToolbarMode(int newMode)
  {
    switch(newMode)
    {
      case JreepadPrefs.TOOLBAR_TEXT:
        toolBar.setVisible(true);
        toolBarIconic.setVisible(false);
        break;
      case JreepadPrefs.TOOLBAR_ICON:
        toolBar.setVisible(false);
        toolBarIconic.setVisible(true);
        break;
      case JreepadPrefs.TOOLBAR_OFF:
        toolBar.setVisible(false);
        toolBarIconic.setVisible(false);
        break;
      default:
        // Invalid mode passed
        return;
    }
    getPrefs().toolbarMode = newMode;
    viewToolbarIconsMenuItem.setSelected(newMode==JreepadPrefs.TOOLBAR_ICON);
    viewToolbarTextMenuItem.setSelected(newMode==JreepadPrefs.TOOLBAR_TEXT);
    viewToolbarOffMenuItem.setSelected(newMode==JreepadPrefs.TOOLBAR_OFF);
    repaint();
  }

  public void establishAutosaveDialogue()
  {
    Box vBox, hBox;
    // Establish the autosave dialogue box
    autoSaveDialog = new JDialog(this, lang.getString("AUTOSAVE"), true);
    autoSaveDialog.setVisible(false);
    vBox = Box.createVerticalBox();
    vBox.add(Box.createGlue());
    hBox = Box.createHorizontalBox();
    hBox.add(autoSaveCheckBox = new JCheckBox(lang.getString("AUTOSAVE_EVERY"), getPrefs().autoSave));
//DSpinner version:    hBox.add(autoSavePeriodSpinner = new DSpinner(1, 1000, getPrefs().autoSavePeriod));
    hBox.add(autoSavePeriodSpinner = new JSpinner(new SpinnerNumberModel(getPrefs().autoSavePeriod, 1, 1000, 1)));
    hBox.add(new JLabel(lang.getString("AUTOSAVE_MINUTES")));
    vBox.add(hBox);
    vBox.add(Box.createGlue());
    hBox = Box.createHorizontalBox();
    hBox.add(autoSaveOkButton = new JButton(lang.getString("OK")));
    hBox.add(autoSaveCancelButton = new JButton(lang.getString("CANCEL")));
    autoSaveOkButton.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e){
                                    getPrefs().autoSavePeriod = ((Integer)(autoSavePeriodSpinner.getValue())).intValue();
//                  getPrefs().autoSavePeriod = autoSavePeriodSpinner.getValue();
                                    getPrefs().autoSave = autoSaveCheckBox.isSelected();
                                    autoSaveDialog.setVisible(false);
                                    if(getPrefs().autoSave && !(autoSaveThread.isAlive()))
                                    {
                                      autoSaveWarningMessage();
                                        autoSaveThread.start();
                                    }
                                    updateWindowTitle();
                                   }});
    autoSaveCancelButton.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e){autoSaveDialog.setVisible(false);}});
    vBox.add(Box.createGlue());
    vBox.add(hBox);
    autoSaveDialog.getContentPane().add(vBox);
    // Finished establishing the autosave dialogue box
  }

  public void autoSaveWarningMessage()
  {
      JOptionPane.showMessageDialog(this, lang.getString("AUTOSAVE_ACTIVE_LONG"), lang.getString("AUTOSAVE_ACTIVE") , JOptionPane.INFORMATION_MESSAGE);
  }

  public void establishNodeUrlDisplayDialogue()
  {
    Box vBox;
    // Establish the nodeUrlDisplay dialogue box
    nodeUrlDisplayDialog = new JDialog(this, "Node URL", true);
    nodeUrlDisplayDialog.setVisible(false);
    vBox = Box.createVerticalBox();
    vBox.add(new JLabel(lang.getString("MSG_NODEURL1")));
    vBox.add(nodeUrlDisplayField = new JTextField("node://its/a/secret"));
    vBox.add(new JLabel(lang.getString("MSG_NODEURL2")));
    vBox.add(nodeUrlDisplayOkButton = new JButton(lang.getString("OK")));
    nodeUrlDisplayOkButton.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e){
                                    nodeUrlDisplayDialog.setVisible(false);
                                   }});
    nodeUrlDisplayDialog.getContentPane().add(vBox);
    // Finished: Establish the nodeUrlDisplay dialogue box
  }

  public static void main(String[] args)
  {

    // System.err.println("" + args.length + " input arguments provided.");
    // for(int i=0; i<args.length; i++){
    //   System.err.println(args[i]);
    // }

    try
    {
      UIManager.setLookAndFeel(
      UIManager.getSystemLookAndFeelClassName());
    } catch (Exception e)
    {}

    String launchFilename="", launchPrefsFilename=null;

    int ARGMODE_FILE = 0;
    int ARGMODE_PREF = 1;
    int argMode = ARGMODE_FILE;

    for(int i=0; i<args.length; i++)
    {
      if(args[i].startsWith("-h") || args[i].startsWith("--h"))
      {
        System.out.println("Jreepad command-line arguments:");
        System.out.println("  -p [prefsfile]    Load/save preferences from named location instead of default");
        System.out.println("  [filename]        Jreepad/treepad file to load on startup");
        System.out.println("  ");
        System.out.println("For example:");
        System.out.println("  java -jar Jreepad.jar -p /Users/jo/Library/jreeprefs.dat /Users/jo/Documents/mynotes.hjt");
        System.exit(1);
      }
      else if(args[i].equals("-p"))
        argMode = ARGMODE_PREF;
      else if(argMode == ARGMODE_PREF && launchPrefsFilename==null)
      {
        launchPrefsFilename=args[i];
        argMode = ARGMODE_FILE;
      }
      else if(argMode == ARGMODE_FILE && launchFilename.equals(""))
      {
        launchFilename=args[i];
      }
    }

    // System.err.println("Launching using prefs file \"" + launchPrefsFilename + "\" and loadfile \"" + launchFilename + "\"\n");

    new JreepadViewer(launchFilename, launchPrefsFilename);

    /*
    The old way of handling the arguments

    if(args.length==0)
      new JreepadViewer();
    else if(args.length==1)
      new JreepadViewer(args[0]);
    else
      System.err.println("Only one (optional) argument can be passed - the name of the HJT file to load.");
    */

  }

  /**
   * Ask the user whether to save the current file if it is unsaved.
   * @param prompt  message to display
   * @return true if the user clicked "Yes" and the save was successful or the user clicked "No" or the file didn't need to be saved;
   *         false if the user clicked "Cancel" or the save failed
   */
  private boolean askAndSave(String prompt)
  {
    if (document.isContentSaved())
      return true;
    int answer = JOptionPane.showConfirmDialog(this, prompt,
                       "Save?" , JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
    if(answer == JOptionPane.CANCEL_OPTION)
      return false;
    if(answer == JOptionPane.YES_OPTION)
    {
      SaveAction saveAction = new SaveAction();
      saveAction.actionPerformed(null);
      if (!saveAction.isSuccessful())
        return false;
    }
    return true;
  }

  private void newAction()
  {
    if (!askAndSave(lang.getString("PROMPT_SAVE_BEFORE_NEW")))
      return;

    content.remove(theJreepad);
    document = new JreepadTreeModel();
    theJreepad = new JreepadView(document);
    content.add(theJreepad);
    searchDialog.setJreepad(theJreepad);

    setTitleBasedOnFilename("");
    validate();
    repaint();
    document.setContentSaved(true);
    updateUndoRedoMenuState();
//  theJreepad.clearUndoCache();
  }

  private void openAction()
  {
    if (!askAndSave(lang.getString("PROMPT_SAVE_BEFORE_OPEN")))
      return;

    fileChooser.setCurrentDirectory(getPrefs().openLocation);
    if(fileChooser.showOpenDialog(this) != JFileChooser.APPROVE_OPTION)
        return;

    setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    openFile(fileChooser.getSelectedFile());
    setCursor(Cursor.getDefaultCursor());
    updateUndoRedoMenuState();
  } // End of: openAction()

  public boolean openFile(File file)
  {
    getPrefs().openLocation = file; // Remember the open directory
    try
    {
      InputStream in = new FileInputStream(file);
      JreepadReader reader = new AutoDetectReader(getPrefs().getEncoding(), getPrefs().autoDetectHtmlArticles);
      document = reader.read(in);
      document.setSaveLocation(file);
    }
    catch(IOException e)
    {
      JOptionPane.showMessageDialog(this, e, lang.getString("MSG_LOAD_FILE_FAILED") , JOptionPane.ERROR_MESSAGE);
      return false;
    }
    content.remove(theJreepad);
    theJreepad = new JreepadView(document);
    content.add(theJreepad);
    searchDialog.setJreepad(theJreepad);

    getPrefs().exportLocation = getPrefs().importLocation = file;
    setTitleBasedOnFilename(file.getName());
    validate();
    repaint();
    return true;
  }

  private class SaveAction extends AbstractAction
  {
    private boolean askForFilename;

    private boolean successful = false;

    public SaveAction()
    {
        this(false);
    }

    public SaveAction(boolean askForFilename)
    {
        super(askForFilename ? lang.getString("MENUITEM_SAVEAS") : lang.getString("MENUITEM_SAVE"),
                getIcon("Save16.gif"));
        this.askForFilename = askForFilename;

        if (askForFilename)
        {
            putValue(MNEMONIC_KEY, new Integer(KeyEvent.VK_A));
            putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke('A', MENU_MASK));
        }
        else
        {
            putValue(MNEMONIC_KEY, new Integer(KeyEvent.VK_S));
            putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke('S', MENU_MASK));
            putValue(SHORT_DESCRIPTION, lang.getString("TOOLBAR_SAVE"));
        }
    }

    public void actionPerformed(ActionEvent e)
    {
        int fileType = getPrefs().mainFileType;
        if (document.getSaveLocation() != null)
            fileType = document.getFileType();

        File saveLocation = document.getSaveLocation();
        if(askForFilename || saveLocation==null || (saveLocation.isFile() && !saveLocation.canWrite()))
        {
          // Ask for filename
          SaveFileChooser fileChooser = new SaveFileChooser(getPrefs().mainFileType);
          fileChooser.setCurrentDirectory(getPrefs().openLocation);

          fileChooser.setSelectedFile(new File(document.getRootNode().getTitle() +
                       (fileType==JreepadPrefs.FILETYPE_XML?".jree":".hjt")));
          if(fileChooser.showSaveDialog(JreepadViewer.this) != JFileChooser.APPROVE_OPTION)
          {
              successful = false;
              return; // No file chosen
          }
          saveLocation = fileChooser.getSelectedFile();
          fileType = fileChooser.getFileType();
        }
        getPrefs().openLocation = saveLocation; // Remember the file's directory

        // Save the file
        try
        {
          setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

          // Select default application encoding or document encoding
          String encoding;
          if (askForFilename || document.getEncoding() == null)
            encoding = getPrefs().getEncoding();
          else
            encoding = document.getEncoding();

          // Write to either HJT or XML
          JreepadWriter writer;
          if(fileType == JreepadPrefs.FILETYPE_XML)
            writer = new XmlWriter();
          else if (fileType == JreepadPrefs.FILETYPE_XML_ENCRYPTED)
          {
              String password = document.getPassword();
              if (password == null || askForFilename)
                  password = PasswordDialog.showPasswordDialog(true);
              if (password == null)
              {
                  successful = false; // "Cancel" was pressed
                  return;
              }
              EncryptedWriter encryptedWriter = new EncryptedWriter(new XmlWriter());
              encryptedWriter.setPassword(password);
              writer = encryptedWriter;
              document.setPassword(password);
          }
          else
            writer = new TreepadWriter(encoding);

          OutputStream fos = new FileOutputStream(saveLocation);
          writer.write(fos, document);
          fos.close();

          if(MAC_OS_X){
            com.apple.eio.FileManager.setFileTypeAndCreator(saveLocation.toString(),
                    appleAppCode, appleAppCode);
          }

          // When calling "Save As..." remember the _new_ file settings
          document.setSaveLocation(saveLocation);
          document.setFileType(fileType);
          document.setEncoding(encoding);

          updateWindowTitle();
          addToOpenRecentMenu(saveLocation);
          savePreferencesFile();
          setCursor(Cursor.getDefaultCursor());
          successful = true;
        }
        catch(IOException err)
        {
          setCursor(Cursor.getDefaultCursor());
          JOptionPane.showMessageDialog(JreepadViewer.this, err, lang.getString("TITLE_FILE_ERROR") , JOptionPane.ERROR_MESSAGE);
          successful = false;
        }
    }

    public boolean isSuccessful()
    {
        return successful;
    }
  }

  private boolean backupToAction()
  {
    try
    {
      fileChooser.setCurrentDirectory(getPrefs().backupLocation);
      if(fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION && checkOverwrite(fileChooser.getSelectedFile()))
      {
        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        getPrefs().backupLocation = fileChooser.getSelectedFile();

        // Write to either HJT
        JreepadWriter writer = new TreepadWriter(getPrefs().getEncoding());
        OutputStream fos = new FileOutputStream(getPrefs().backupLocation);
        writer.write(fos, document);
        fos.close();

        setCursor(Cursor.getDefaultCursor());
        return true;
      }
      else
        return false;
    }
    catch(IOException err)
    {
      setCursor(Cursor.getDefaultCursor());
      JOptionPane.showMessageDialog(this, err, lang.getString("TITLE_FILE_ERROR") , JOptionPane.ERROR_MESSAGE);
    }
    return false;
  } // End of: backupToAction()


  private void setTitleBasedOnFilename(String filename)
  {
    if(filename=="")
      windowTitle = "Jreepad (Java Treepad Editor)";
    else
      windowTitle = filename + " - Jreepad";
    updateWindowTitle();
  }

  private void updateWindowTitle()
  {
    setTitle(windowTitle + (document.isContentSaved()?"":"*") + (getPrefs().autoSave?" ["+lang.getString("AUTOSAVE_ACTIVE")+"]":""));
  }

  private static final int FILE_FORMAT_HJT=1;
  private static final int FILE_FORMAT_HTML=2;
  private static final int FILE_FORMAT_XML=3;
  private static final int FILE_FORMAT_TEXT=4;
  private static final int FILE_FORMAT_TEXTASLIST=5;
  private static final int FILE_FORMAT_ARTICLESTOTEXT=6;
  private void importAction(int importFormat)
  {
    boolean multipleFiles;
    try
    {

      multipleFiles = (importFormat == FILE_FORMAT_TEXT);

      if(multipleFiles)
        fileChooser.setMultiSelectionEnabled(true);
      fileChooser.setCurrentDirectory(getPrefs().importLocation);
      fileChooser.setSelectedFile(new File(theJreepad.getCurrentNode().getTitle()));

      if(fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION)
      {
        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        getPrefs().importLocation = fileChooser.getSelectedFile();

        switch(importFormat)
        {
          case FILE_FORMAT_HJT:
            InputStream in = new FileInputStream(getPrefs().importLocation);
            JreepadReader reader = new AutoDetectReader(getPrefs().getEncoding(), getPrefs().autoDetectHtmlArticles);
            theJreepad.addChild(reader.read(in).getRootNode());
            break;
          case FILE_FORMAT_TEXT:
            theJreepad.addChildrenFromTextFiles(fileChooser.getSelectedFiles());
            break;
          case FILE_FORMAT_TEXTASLIST:
            theJreepad.addChildrenFromListTextFile(new InputStreamReader(new FileInputStream(getPrefs().importLocation), getPrefs().getEncoding()));
            break;
          default:
            setCursor(Cursor.getDefaultCursor());
            JOptionPane.showMessageDialog(this,  "Unknown which format to import - coding error! Oops!",lang.getString("TITLE_MISC_ERROR") , JOptionPane.ERROR_MESSAGE);
            return;
        }
        updateWindowTitle();
      }
      fileChooser.setMultiSelectionEnabled(false);
      setCursor(Cursor.getDefaultCursor());
    }
    catch(IOException err)
    {
      setCursor(Cursor.getDefaultCursor());
      JOptionPane.showMessageDialog(this, err, lang.getString("TITLE_MISC_ERROR") , JOptionPane.ERROR_MESSAGE);
    }
  } // End of: importAction()

  private void exportAction(int exportFormat)
  {
    try
    {
      fileChooser.setCurrentDirectory(getPrefs().exportLocation);
      String suggestFilename = theJreepad.getCurrentNode().getTitle();
      switch(exportFormat)
      {
        case FILE_FORMAT_HJT:
          suggestFilename += ".hjt";
          break;
        case FILE_FORMAT_HTML:
          suggestFilename += ".html";
          break;
        case FILE_FORMAT_XML:
          suggestFilename += ".xml";
          break;
        case FILE_FORMAT_TEXT:
        case FILE_FORMAT_TEXTASLIST:
        case FILE_FORMAT_ARTICLESTOTEXT:
          suggestFilename += ".txt";
          break;
      }
      fileChooser.setSelectedFile(new File(suggestFilename));
      if(fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION && checkOverwrite(fileChooser.getSelectedFile()))
      {
        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        getPrefs().exportLocation = fileChooser.getSelectedFile();

        String output = null;
        JreepadWriter writer = null;
        switch(exportFormat)
        {
          case FILE_FORMAT_HTML:
            writer = new HtmlWriter(getPrefs().getEncoding(),
                getPrefs().htmlExportArticleType,
                getPrefs().htmlExportUrlsToLinks,
                getPrefs().htmlExportAnchorLinkType);
            break;
          case FILE_FORMAT_XML:
            writer= new XmlWriter();
            break;
          case FILE_FORMAT_HJT:
            writer= new TreepadWriter(getPrefs().getEncoding());
            break;
          case FILE_FORMAT_TEXT:
            output = theJreepad.getCurrentNode().getContent();
            break;
          case FILE_FORMAT_TEXTASLIST:
            output = theJreepad.getCurrentNode().exportTitlesAsList();
            break;
          case FILE_FORMAT_ARTICLESTOTEXT:
            int answer = JOptionPane.showConfirmDialog(this, lang.getString("PROMPT_INCLUDE_TITLES"),
                       lang.getString("TITLE_INCLUDE_TITLES") , JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
            boolean titlesToo = (answer == JOptionPane.YES_OPTION);
            output = theJreepad.getCurrentNode().exportArticlesToText(titlesToo);
            break;
          default:
            setCursor(Cursor.getDefaultCursor());
            JOptionPane.showMessageDialog(this,  "Unknown which format to export - coding error! Oops!",lang.getString("TITLE_MISC_ERROR") , JOptionPane.ERROR_MESSAGE);
            return;
        }

        OutputStream fos = new FileOutputStream(getPrefs().exportLocation);
        if (writer != null)
        {
          writer.write(fos, new JreepadTreeModel(theJreepad.getCurrentNode()));
          fos.close();
        }
        else // assume (output != null)
        {
          OutputStreamWriter osw = new OutputStreamWriter(fos, getPrefs().getEncoding());
          osw.write(output);
          osw.close();
        }
        setCursor(Cursor.getDefaultCursor());
      }
    }
    catch(IOException err)
    {
      setCursor(Cursor.getDefaultCursor());
      JOptionPane.showMessageDialog(this, err, lang.getString("TITLE_FILE_ERROR") , JOptionPane.ERROR_MESSAGE);
    }
  } // End of: exportAction()

  private void subtreeToBrowserForPrintAction()
  {
    setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

    HtmlWriter writer = new HtmlWriter(
        getPrefs().getEncoding(),
        getPrefs().htmlExportArticleType,
        getPrefs().htmlExportUrlsToLinks,
        getPrefs().htmlExportAnchorLinkType,
        true);
    String output = writer.write(theJreepad.getCurrentNode());

    toBrowserForPrintAction(output);

    setCursor(Cursor.getDefaultCursor());
  } // End of: subtreeToBrowserForPrintAction()

  private void articleToBrowserForPrintAction()
  {
    setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

    String output = theJreepad.getCurrentNode().getArticle().exportAsHtml(
      getPrefs().htmlExportArticleType, getPrefs().htmlExportUrlsToLinks,
      getPrefs().htmlExportAnchorLinkType, true);

    toBrowserForPrintAction(output);
    setCursor(Cursor.getDefaultCursor());
  } // End of: articleToBrowserForPrintAction()

  private void toBrowserForPrintAction(String output)
  {
    String surl = "";
    try
    {
      File systemTempFile = File.createTempFile("TMPjree", ".html");

      FileOutputStream fO = new FileOutputStream(systemTempFile);
      DataOutputStream dO = new DataOutputStream(fO);
      dO.writeBytes(output);
      dO.close();
      fO.close();
      setCursor(Cursor.getDefaultCursor());

      // Now launch the file in a browser...
      surl = systemTempFile.toURL().toString();
      new BrowserLauncher(null).openURLinBrowser(surl);
    }
    catch (BrowserLaunchingInitializingException e)
    {
      displayBrowserLauncherException(e, surl);
    }
    catch (BrowserLaunchingExecutionException e)
    {
      displayBrowserLauncherException(e, surl);
    }
    catch (UnsupportedOperatingSystemException e)
    {
      displayBrowserLauncherException(e, surl);
    }
    catch (IOException err)
    {
      JOptionPane.showMessageDialog(this, err, lang.getString("TITLE_FILE_ERROR"),
        JOptionPane.ERROR_MESSAGE);
    }
  }

  private void displayBrowserLauncherException(Exception e, String url)
  {
    JOptionPane.showMessageDialog(this, "Error while opening URL:\n" + url + "\n"
      + e.getMessage() + "\n\n"
      + "The \"BrowserLauncher\" used to open a URL is an open-source Java library \n"
      + "separate from Jreepad itself - i.e. a separate Sourceforge project. \n"
      + "It may be a good idea to submit a bug report to\n"
      + "http://browserlaunch2.sourceforge.net/\n\n"
      + "If you do, please remember to supply information about the operating system\n"
      + "you are using - which type, and which version.", lang.getString("TITLE_MISC_ERROR"),
      JOptionPane.ERROR_MESSAGE);
  }


  public void quitAction()
  {
    // We need to check about warning-if-unsaved!

    // For a multiple-Jreepad interface, we would need to use:
    //  for(int i=0; i<theApps.length(); i++)
    //  {
    //    currApp = getApp(i);
    //    if(currApp.warnAboutUnsaved())
    //    {
    //

    if (!askAndSave(lang.getString("PROMPT_SAVE_BEFORE_QUIT")))
      return;

    // Save preferences - including window position and size, and open/closed state of the current tree's nodes
    getPrefs().treePathCollection = new TreePathCollection(theJreepad.getAllExpandedPaths());
    getPrefs().windowLeft = getX();
    getPrefs().windowTop = getY();
    getPrefs().windowWidth = getWidth();
    getPrefs().windowHeight = getHeight();
    savePreferencesFile();

    System.exit(0);
  }

  private void savePreferencesFile()
  {
    getPrefs().save();
    /*
    try
    {
      ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(prefsFile));
      out.writeObject(getPrefs());
      out.close();
    }
    catch(IOException err)
    {
    }
    */
  }

  private void setViewMode(int mode)
  {
    theJreepad.setViewMode(mode);
    // Update the dropdown menu
    if(mode==JreepadPrefs.VIEW_ARTICLE){
      viewSelector.setSelectedIndex(2);
    }else if(mode==JreepadPrefs.VIEW_TREE){
      viewSelector.setSelectedIndex(1);
    }else{
      viewSelector.setSelectedIndex(0);
    }

    // Update the preferences object
    getPrefs().viewWhich = mode;

    // Update the undo menus
    updateUndoRedoMenuState();
  }

  private static JreepadPrefs getPrefs() { return JreepadView.getPrefs(); }
  private static void setPrefs(JreepadPrefs thesePrefs) { JreepadView.setPrefs(thesePrefs); }

  private void setViewToolbar(boolean boo)
  {
    toolBar.setVisible(boo);
  }

  private void undoAction()
  {
/*
    if(theJreepad.canWeUndo())
      theJreepad.undoAction();
    else
      JOptionPane.showMessageDialog(this, lang.getString("MSG_NOTHING_TO_UNDO"), "No change" , JOptionPane.INFORMATION_MESSAGE);
*/
    UndoManager undoMgr = theJreepad.getCurrentNode().getArticle().getUndoMgr();
    String undoStyle = undoMgr.getUndoPresentationName();
    try{
      // This "while" should roll multiple adds or deletes into one.
      //System.out.println(undoStyle);
      //System.out.println(undoMgr.getUndoPresentationName());
      while(undoStyle.equals(undoMgr.getUndoPresentationName()))
        undoMgr.undo();
    }catch(CannotUndoException ex){
      //JOptionPane.showMessageDialog(this, lang.getString("MSG_NOTHING_TO_UNDO"), "No change" , JOptionPane.INFORMATION_MESSAGE);
    }
    updateWindowTitle();
    updateUndoRedoMenuState();
  }
  private void redoAction(){
    UndoManager undoMgr = theJreepad.getCurrentNode().getArticle().getUndoMgr();
    String redoStyle = undoMgr.getRedoPresentationName();
    try{
      while(redoStyle.equals(undoMgr.getRedoPresentationName()))
        undoMgr.redo();
    }catch(CannotRedoException ex){
      //JOptionPane.showMessageDialog(this, lang.getString("MSG_NOTHING_TO_UNDO"), "No change" , JOptionPane.INFORMATION_MESSAGE);
    }
    updateWindowTitle();
    updateUndoRedoMenuState();
  }

  public void updateUndoRedoMenuState(){
    undoMenuItem.setEnabled(isArticleUndoPossible());
    redoMenuItem.setEnabled(isArticleRedoPossible());
  }

  public boolean isArticleUndoPossible(){
    if(getPrefs().viewWhich == JreepadPrefs.VIEW_TREE)
      return false;

    if(theJreepad.getCurrentNode().getArticle().getArticleMode() != JreepadArticle.ARTICLEMODE_ORDINARY)
      return false;

    // Deactivated: since this class can't tell if text has been typed or not...
    // if(!theJreepad.getCurrentNode().undoMgr.canUndo())
    //   return false;

    return true;
  }
  public boolean isArticleRedoPossible(){
    if(getPrefs().viewWhich == JreepadPrefs.VIEW_TREE)
      return false;

    if(theJreepad.getCurrentNode().getArticle().getArticleMode() != JreepadArticle.ARTICLEMODE_ORDINARY)
      return false;

    if(!theJreepad.getCurrentNode().getArticle().getUndoMgr().canRedo())
      return false;

    return true;
  }

  private void aboutAction()
  {
              JOptionPane.showMessageDialog(this,
              "Jreepad v " + version + "\n\n" +
              lang.getString("HELP_ABOUT") +
              "\n" +
              "\nJreepad \u00A9 2004-2007 Dan Stowell" +
              "\n" +
              "\nhttp://jreepad.sourceforge.net"
              ,
              "About Jreepad",
              JOptionPane.INFORMATION_MESSAGE);
  }

  private void showAutoSaveDialog()
  {
    // The autosave simply launches a background thread which periodically triggers saveAction if saveLocation != null
    autoSaveCheckBox.setSelected(getPrefs().autoSave);
    autoSavePeriodSpinner.getModel().setValue(new Integer(getPrefs().autoSavePeriod));
//   autoSavePeriodSpinner.setValue(getPrefs().autoSavePeriod);
    autoSaveDialog.setVisible(true);
    autoSaveDialog.toFront();
  }

  private void showPrefsDialog()
  {
    prefsDialog.setVisible(true);
    prefsDialog.toFront();

    // Apply preferences that immediately affect the GUI
    funkyGreenStrip.setVisible(getPrefs().showGreenStrip);
    webSearchMenuItem.setText(getPrefs().webSearchName);
    characterWrapArticleMenuItem.setText(JreepadViewer.lang.getString("MENUITEM_HARDWRAP1")
        + getPrefs().characterWrapWidth + JreepadViewer.lang.getString("MENUITEM_HARDWRAP2"));
  }

  private void deleteNodeAction()
  {
    if(JOptionPane.showConfirmDialog(this, lang.getString("PROMPT_CONFIRM_DELETE")+":\n"+theJreepad.getCurrentNode().getTitle(), lang.getString("TITLE_CONFIRM_DELETE"),
               JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) return;
    theJreepad.removeNode();
    theJreepad.returnFocusToTree();
    updateWindowTitle();
  }

  private void getTreepadNodeUrl()
  {
//    String ret = theJreepad.getTreepadNodeUrl();
    nodeUrlDisplayField.setText(theJreepad.getTreepadNodeUrl());
    nodeUrlDisplayDialog.setVisible(true);
  }

  private boolean checkOverwrite(File theFile)
  {
    // If file doesn't already exist then fine
    if(theFile == null || !theFile.exists())
        return true;

    // Else we need to confirm
    return (JOptionPane.showConfirmDialog(this, lang.getString("PROMPT_CONFIRM_OVERWRITE1")+" "+theFile.getName()+" "+lang.getString("PROMPT_CONFIRM_OVERWRITE2"),
                lang.getString("TITLE_CONFIRM_OVERWRITE"),
                JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION);
  }

  public void showLicense()
  {
              JOptionPane.showMessageDialog(this,
lang.getString("HELP_LICENSE") + "\n\n           http://www.gnu.org/copyleft/gpl.html\n" +
             "\n"
              ,
              lang.getString("MENUITEM_LICENSE"),
              JOptionPane.INFORMATION_MESSAGE);
  }

  public void wrapContentToCharWidth()
  {
    theJreepad.wrapContentToCharWidth(getPrefs().characterWrapWidth);
  }
  public void stripAllTags()
  {
    if(JOptionPane.showConfirmDialog(this, lang.getString("PROMPT_CONFIRM_STRIPTAGS"),
                lang.getString("TITLE_CONFIRM_STRIPTAGS"),
                JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION)
      theJreepad.stripAllTags();
  }


  private void addToOpenRecentMenu(File f)
  {
    // Remove the file from the list if it's already in there...
    ListIterator iter = getPrefs().openRecentList.listIterator();
    File tempFile;
    while(iter.hasNext())
    {
      tempFile = (File)iter.next();
      if(tempFile == null || tempFile.equals(f))
        iter.remove();
    }

    getPrefs().openRecentList.insertElementAt(f, 0);
    updateOpenRecentMenu();
  }
  private File[] openRecentTempFileList;
  private void updateOpenRecentMenu()
  {
    if(getPrefs().openRecentList.size() > getPrefs().openRecentListLength)
      getPrefs().openRecentList.setSize(getPrefs().openRecentListLength);

    try
    {
//      openRecentTempFileList = (File[])getPrefs().openRecentList.toArray();
      openRecentTempFileList = new File[getPrefs().openRecentList.size()];
      for(int i=0; i<getPrefs().openRecentList.size(); i++)
      {
        openRecentTempFileList[i] = (File)getPrefs().openRecentList.get(i);
      }
    }
    catch(ClassCastException e)
    {
      System.err.println(e);
      openRecentTempFileList = new File[0];
    }

    openRecentMenu.setEnabled(getPrefs().openRecentList.size()>1);

    openRecentMenu.removeAll();

    JMenuItem tempMenuItem;
    File tempFile;
    char theChar;
    for(int i=1; i<openRecentTempFileList.length; i++)
    {
      tempFile = openRecentTempFileList[i];
      tempMenuItem = new JMenuItem(tempFile.getParentFile().getName() + "/" + tempFile.getName());
      if(i<10)
      {
        theChar = ("" + i).charAt(0);
        tempMenuItem.setText("("+theChar+") "+tempMenuItem.getText());
        tempMenuItem.setMnemonic(theChar);
      }
      // ADD THE ACTIONLISTENER HERE
      tempMenuItem.addActionListener(new FileOpeningActionListener(tempFile));
      openRecentMenu.add(tempMenuItem);
    }
  }

  private void insertDate()
  {
    theJreepad.insertDate();
  }

  private class FileOpeningActionListener implements ActionListener
  {
    File f;
    FileOpeningActionListener(File f)        {this.f = f;}
    public void actionPerformed(ActionEvent e) {openFile(f);}
  } // End of:   private class FileOpeningActionListener extends ActionListener


//  private void updateFontsInPrefsBox()
//  {
//    String treeFontName = getPrefs().treeFont.getFamily();
//    String articleFontName = getPrefs().articleFont.getFamily();
//    String treeFontSize = "" + getPrefs().treeFont.getSize();
//    String articleFontSize = "" + getPrefs().articleFont.getSize();

//    int i;
//    for(i=0; i<fonts.length; i++)
//    {
//      if(treeFontName.equals(fonts[i]))
//        treeFontFamilySelector.setSelectedIndex(i);
//      if(articleFontName.equals(fonts[i]))
//      {
//        articleFontFamilySelector.setSelectedIndex(i);
//        break;
//      }
//    }
//    for(i=0; i<fontSizes.length; i++)
//    {
//      if(treeFontSize.equals(fontSizes[i]))
//        treeFontSizeSelector.setSelectedIndex(i);
//      if(articleFontSize.equals(fontSizes[i]))
//      {
//        articleFontSizeSelector.setSelectedIndex(i);
//        break;
//      }
//    }
//  }

//  private void setFontsFromPrefsBox()
//  {
//    getPrefs().treeFont = new Font((String)treeFontFamilySelector.getSelectedItem(), Font.PLAIN,
//                   getPrefs().treeFont.getSize() );
//    getPrefs().articleFont = new Font((String)articleFontFamilySelector.getSelectedItem(), Font.PLAIN,
//                   (Integer.valueOf((String)articleFontSizeSelector.getSelectedItem())).intValue()  );
//    theJreepad.setTreeFont(getPrefs().treeFont);
//    theJreepad.setArticleFont(getPrefs().articleFont);
//  }



// Generic registration with the Mac OS X application menu.  Checks the platform, then attempts
  // to register with the Apple EAWT.
  // This method calls OSXAdapter.registerMacOSXApplication() and OSXAdapter.enablePrefs().
  // See OSXAdapter.java for the signatures of these methods.
  public void macOSXRegistration() {
    if (MAC_OS_X) {
      try {
        Class osxAdapter = Class.forName("jreepad.OSXAdapter");

        Class[] defArgs = {JreepadViewer.class};
        Method registerMethod = osxAdapter.getDeclaredMethod("registerMacOSXApplication", defArgs);
        if (registerMethod != null) {
          Object[] args = { this };
          registerMethod.invoke(osxAdapter, args);
        }
/*
        // This is slightly gross.  to reflectively access methods with boolean args,
        // use "boolean.class", then pass a Boolean object in as the arg, which apparently
        // gets converted for you by the reflection system.
        defArgs[0] = boolean.class;
        Method prefsEnableMethod =  osxAdapter.getDeclaredMethod("enablePrefs", defArgs);
        if (prefsEnableMethod != null) {
          Object args[] = {Boolean.TRUE};
          prefsEnableMethod.invoke(osxAdapter, args);
        }
*/
      } catch (NoClassDefFoundError e) {
        // This will be thrown first if the OSXAdapter is loaded on a system without the EAWT
        // because OSXAdapter extends ApplicationAdapter in its def
        System.err.println("This version of Mac OS X does not support the Apple EAWT.  Application Menu handling has been disabled (" + e + ")");
      } catch (ClassNotFoundException e) {
        // This shouldn't be reached; if there's a problem with the OSXAdapter we should get the
        // above NoClassDefFoundError first.
        System.err.println("This version of Mac OS X does not support the Apple EAWT.  Application Menu handling has been disabled (" + e + ")");
      } catch (Exception e) {
        System.err.println("Exception while loading the OSXAdapter:");
        e.printStackTrace();
      }
    }
  }


// General info dialog.  The OSXAdapter calls this method when "About OSXAdapter"
  // is selected from the application menu.
  public void about() {
    aboutAction();
  }

  // General preferences dialog.  The OSXAdapter calls this method when "Preferences..."
  // is selected from the application menu.
  public void preferences() {
//    prefs.setSize(320, 240);
//    prefs.setLocation((int)this.getLocation().getX() + 22, (int)this.getLocation().getY() + 22);
//    prefs.setResizable(false);
//    prefs.setVisible(true);
  }

  // General info dialog.  The OSXAdapter calls this method when "Quit OSXAdapter"
  // is selected from the application menu, Cmd-Q is pressed, or "Quit" is selected from the Dock.
  public void quit() {
      quitAction();
  }


  protected void systemClipboardToNewNode()
  {
    Transferable cont = systemClipboard.getContents(this);

/*
    DataFlavor[] flavs = cont.getTransferDataFlavors();
    System.out.println("Data flavors supported by contents:\n");
    for(int i=0; i<flavs.length; i++)
      System.out.println("  " + flavs[i].getHumanPresentableName() + "\n"
                              + flavs[i].getMimeType() + "\n");
*/

    if(cont == null)
    {
      JOptionPane.showMessageDialog(this, lang.getString("MSG_CLIPBOARD_EMPTY"), lang.getString("TITLE_CLIPBOARD_EMPTY") , JOptionPane.ERROR_MESSAGE);
      return;
    }
    try
    {
//      Reader readIt = DataFlavor.getTextPlainUnicodeFlavor().getReaderForText(cont);
      Reader readIt = DataFlavor.stringFlavor.getReaderForText(cont);
      char[] theStuff = new char[64];
      int numRead;
      StringBuffer theStuffBuf = new StringBuffer();
      while((numRead = readIt.read(theStuff)) != -1)
      {
        theStuffBuf.append(theStuff, 0, numRead);
      }

      String contStr = theStuffBuf.toString();
      String titStr;
      int newlinePos = contStr.indexOf("\n");
      if(newlinePos == -1)
      {
        titStr = contStr;
        contStr = "";
      }
      else
        titStr = contStr.substring(0, newlinePos-1);
      theJreepad.addChild(new JreepadNode(titStr, contStr));
    }
    catch(Exception err)
    {
      JOptionPane.showMessageDialog(this, lang.getString("MSG_CLIPBOARD_TEXTERROR"), lang.getString("TITLE_CLIPBOARD_ERROR") , JOptionPane.ERROR_MESSAGE);
      return;
    }
  }

  public void keyboardHelp()
  {
    String menuText;
    if(MAC_OS_X)
      menuText = "Apple";
    else
      switch(MENU_MASK)
      {
        case Event.ALT_MASK:
          menuText = "Alt";
          break;
        case Event.META_MASK:
          menuText = "Meta";
          break;
        case Event.CTRL_MASK:
        default:
          menuText = "Ctrl";
          break;
      }
              JOptionPane.showMessageDialog(this,
              "\nNAVIGATING AROUND THE TREE:" +
              "\nUse the arrow (cursor) keys to navigate around the tree." +
              "\nUp/down will move you up/down the visible nodes." +
              "\nLeft/right will expand/collapse nodes." +
              "\n" +
              "\nADDING/DELETING NODES:" +
              "\n["+menuText+"+T] Add sibling node above current node" +
              "\n["+menuText+"+B] Add sibling node below current node" +
              "\n["+menuText+"+D] Add child node to current node" +
              "\n["+menuText+"+K] Delete current node" +
              "\n" +
              "\nMOVING NODES:" +
              "\n["+menuText+"+up arrow] Move node up" +
              "\n["+menuText+"+down arrow] Move node down" +
              "\n["+menuText+"+right arrow] Indent node" +
              "\n["+menuText+"+left arrow] Outdent node" +
              "\n" +
              "\nCOPYING AND PASTING:" +
              "\n["+menuText+"+X] Cut selected text" +
              "\n["+menuText+"+C] Copy selected text" +
              "\n["+menuText+"+V] Paste selected text" +
              "\n - The copy/paste functions are included automatically" +
              "\n    by the Mac OSX runtime. I can't guarantee they exist" +
              "\n    for you if you're using a different operating system!" +
/*
             "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n[] " +
              "\n" +
*/
             ""
              ,
              lang.getString("HELP_KEYBOARD_TITLE"),
              JOptionPane.INFORMATION_MESSAGE);
  }

  public void linksHelp()
  {
              JOptionPane.showMessageDialog(this,
              lang.getString("HELP_LINKS")
/*
              "\nSelect any piece of text in an article," +
              "\nthen choose \"Actions > Follow link in article\"." +
              "\n" +
              "\nTYPES OF LINK:" +
              "\n" +
              "\n\"Normal\" link - We've tested these types of link:" +
              "\n      Web:   e.g. http://jreepad.sourceforge.net" +
              "\n      Email: e.g. mailto:billg@microsoft.com" +
              "\n      FTP:   e.g. ftp://ftp.compaq.com/pub/" +
              "\n      File:  (can't get these to work, on OSX at least)" +
              "\n" +
              "\nWiki link - If the selected text is a WikiWord (i.e. if " +
              "\n            it LooksLikeThis with no spaces and some capital " +
              "\n            letters somewhere in the middle) OR begins " +
              "\n            with \"[[\" and ends with \"]]\" then " +
              "\n            Jreepad will search for a node of the same " +
              "\n            title, and jump directly to it. If one " +
              "\n            isn't found then it'll create one " +
              "\n            for you. Try it!" +
              "\n" +
              "\nTreepad link - Treepad Lite uses links which begin " +
              "\n            with \"node://\", and specify the exact path" +
              "\n            to a different node within the same file."+
              "\n              e.g. \"node://TreePad manual/Using Treepad\"" +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n[] " +
              "\n" +
              ""
*/
              ,
              lang.getString("HELP_LINKS_TITLE"),
              JOptionPane.INFORMATION_MESSAGE);
  }

  public void dragDropHelp()
  {
              JOptionPane.showMessageDialog(this,
              lang.getString("HELP_DRAGDROP")
/*
              "\nDRAG-AND-DROP:" +
              "\n" +
              "\nOne of the easiest ways to manage the structure" +
              "\nof your Treepad file is to drag the nodes around" +
              "\nusing the mouse." +
              "\n" +
              "\nClick on a node's title, and, keeping the mouse" +
              "\nbutton held down, move the mouse to where you" +
              "\nwant the node to be moved to. Then release the" +
              "\nmouse button, and the node will be moved to its" +
              "\nnew position in the tree." +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n" +
              "\n[] " +
              "\n" +
              ""
*/
              ,
              lang.getString("HELP_DRAGDROP_TITLE"),
              JOptionPane.INFORMATION_MESSAGE);
  }


/*
  // Replacement for the "JSpinner" which is not available in Java 1.3 or 1.2
  static class DSpinner extends Box
  {
    private int min, max, val;
    private JTextField textField;
    private JButton upBut, downBut;
    private ActionListener al;

    DSpinner(int min, int max, int myVal)
    {
      super(BoxLayout.X_AXIS);
      this.min=this.val=min;
      this.max=max;
      this.add(Box.createGlue());
      this.add(textField = new JTextField(val));
      this.add(downBut = new JButton("-"));
      this.add(upBut = new JButton("+"));
      this.add(Box.createGlue());

      downBut.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {
                              setValue(val-1);
                              if(al!=null)
                                al.actionPerformed(null);
                              }});
      upBut.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e) {
                              setValue(val+1);
                              if(al!=null)
                                al.actionPerformed(null);
                              }});
      setValue(myVal);
    }

    int getValue()
    {
      try
      {
        val = Integer.parseInt(textField.getText());
      }
      catch(NumberFormatException e)
      {
      }
      return val;
    }
    void setValue(int newVal)
    {
      if(newVal>=min && newVal<=max)
        val=newVal;
        textField.setText("" + val);
    }
    void addActionListener(ActionListener al)
    {
      this.al = al;
      textField.addActionListener(al);
    }
    void addCaretListener(CaretListener cl)
    {
      textField.addCaretListener(cl);
    }

  } // End of class DSpinner
*/

  static class ColouredStrip extends JPanel
  {
    Color col;
    ColouredStrip(Color col, int maxWidth, int maxHeight)
    {
      super(false);
      setMaximumSize(new Dimension(maxWidth, maxHeight));
      setBackground(col);
//      this.col = col;
    }

//    public void paint(Graphics gggg)
//    {
//      Graphics2D g = (Graphics2D)gggg;
//      g.setPaint(col);
//      g.fillRect(0,0,getWidth(),getHeight());
//    }
  }




/*
  // Methods required by Apple's "ApplicationListener" interface
  public void handleOpenFile(ApplicationEvent ae)
  {
     System.err.println("Jreepad.handleOpenFile() - ApplicationEvent is " + ae);
     openHjtFile(new java.io.File(ae.getFilename()));
     ae.setHandled(true);
  }
  public void handleOpenApplication(ApplicationEvent ae)
  {
     System.err.println("Jreepad.handleOpenApplication() - ApplicationEvent is " + ae);
  }
  public void handleReOpenApplication(ApplicationEvent ae)
  {
     System.err.println("Jreepad.handleReOpenApplication() - ApplicationEvent is " + ae);
  }
  public void handlePrintFile(ApplicationEvent ae)
  {
     System.err.println("Jreepad.handlePrintFile() - ApplicationEvent is " + ae);
     ae.setHandled(true);
     toBrowserForPrintAction();
  }
    public void handleAbout(ApplicationEvent ae) {
        ae.setHandled(true);
        about();
    }
    public void handlePreferences(ApplicationEvent ae) {
        preferences();
        ae.setHandled(true);
    }
    public void handleQuit(ApplicationEvent ae) {
        //
        //  You MUST setHandled(false) if you want to delay or cancel the quit.
        //  This is important for cross-platform development -- have a universal quit
        //  routine that chooses whether or not to quit, so the functionality is identical
        //  on all platforms.  This example simply cancels the AppleEvent-based quit and
        //  defers to that universal method.
        //
        ae.setHandled(false);
        quit();
    }
*/
}
TOP

Related Classes of jreepad.JreepadViewer$SaveAction

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