/*
 * jNPad v0.3 - jNPad's an Simple Text Editor written in Java
 *
 * Copyright (C) 2014-2017  rgs
 *
 * Require JDK 1.6 (or later)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 *
 * Info, Questions, Suggestions & Bugs Report to rgsevero@gmail.com
 */

package jnpad;

import java.awt.Component;
import java.awt.Insets;
import java.awt.SystemTray;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;

import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import jnpad.GUIUtilities.FontSize;
import jnpad.action.OpenRecentFileAction;
import jnpad.action.SelectAutoCompletionFromNthAction;
import jnpad.action.SelectColorSchemeAction;
import jnpad.action.SelectEncodingAction;
import jnpad.action.SelectFontSizeAction;
import jnpad.action.SelectKeymapAction;
import jnpad.action.SelectLAFAction;
import jnpad.action.SelectLanguageAction;
import jnpad.action.SelectModeAction;
import jnpad.action.SelectTabSizeAction;
import jnpad.config.Config;
import jnpad.config.Mode;
import jnpad.ui.JNPadCheckBoxMenuItem;
import jnpad.ui.JNPadMenuBar;
import jnpad.ui.JNPadMenuItem;
import jnpad.ui.JNPadRadioButtonMenuItem;
import jnpad.ui.MnemonicHelper;
import jnpad.ui.plaf.LAFUtils;
import jnpad.ui.toolbar.PopupButton;
import jnpad.util.Utilities;

/**
 * The Class JNPadMenuHelper.
 *
 * @version 0.3
 * @since   jNPad v0.1
 */
final class JNPadMenuHelper {
  JMenuBar           menuBar          = new JNPadMenuBar();
  JMenu              mWindow          = new JMenu();
  JMenu              mFileRecentFiles = new JMenu();
  JPopupMenu         pmRecentFiles    = new JPopupMenu();
  PopupButton        btRecentFiles    = new PopupButton();
  ButtonGroup        bgEOL            = new ButtonGroup();
  ButtonGroup        bgEncoding       = new ButtonGroup();
  ButtonGroup        bgColorScheme    = new ButtonGroup();

  private JNPadFrame jNPad;
  
  /**
   * Instantiates a new jNPad menu helper.
   *
   * @param jNPad the jNPad's frame
   */
  JNPadMenuHelper(JNPadFrame jNPad) {
    this.jNPad = jNPad;

    menuBar.setMargin(new Insets(0, 2, 0, 2));
    menuBar.setBorder(null);
  }

  /**
   * Gets the menu bar.
   *
   * @return the menu bar
   */
  JMenuBar getMenuBar() {
    menuBar.removeAll(); //[added v0.3] 
    
    final JNPadActionHelper actions = jNPad.actions;
    
    menuBar.add(createFileMenu(actions));
    menuBar.add(createEditMenu(actions));
    menuBar.add(createSearchMenu(actions));
    menuBar.add(createViewMenu(actions));
    menuBar.add(createFormatMenu(actions));
    menuBar.add(createConfigureMenu(actions));
    menuBar.add(createWindowMenu(actions));
    menuBar.add(createHelpMenu(actions));
    
    menuBar.add(Box.createHorizontalGlue()); //[added v0.3] 
    menuBar.add(new CloseLabel()); //[added v0.3] 
    
    return menuBar;
  }

  /**
   * Creates the file menu.
   *
   * @param actions the actions
   * @return the menu
   */
  private JMenu createFileMenu(final JNPadActionHelper actions) {
    JMenu mFile = GUIUtilities.createMenu(JNPadBundle.getString("menu.file"), null); //$NON-NLS-1$

    mFile.add(new JNPadMenuItem(actions.newFileAction));

    mFile.addSeparator();

    mFile.add(new JNPadMenuItem(actions.openFileAction));
    GUIUtilities.setLocalizedText(mFileRecentFiles, JNPadBundle.getString("menu.file.recentFiles")); //$NON-NLS-1$
    if (Config.isDefaultMode()) {
      mFileRecentFiles.setIcon(GUIUtilities.loadIcon("reopen.png")); //$NON-NLS-1$
    }
    mFile.add(mFileRecentFiles);
    mFile.add(new JNPadMenuItem(actions.openAllRecentFilesAction));
    mFile.add(new JNPadMenuItem(actions.emptyRecentFilesListAction));
    mFile.addSeparator();
    mFile.add(new JNPadMenuItem(actions.closeFileAction));
    mFile.add(new JNPadMenuItem(actions.closeFilesAction));
    mFile.add(new JNPadMenuItem(actions.closeAllAction));
    JMenu mFileCloseOther = GUIUtilities.createMenu(JNPadBundle.getString("menu.file.closeOther"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    mFileCloseOther.add(new JNPadMenuItem(actions.closeOtherAction));
    mFileCloseOther.add(new JNPadMenuItem(actions.closeAllToLeftAction));
    mFileCloseOther.add(new JNPadMenuItem(actions.closeAllToRightAction));
    mFile.add(mFileCloseOther);

    mFile.addSeparator();

    mFile.add(new JNPadMenuItem(actions.saveFileAction));
    mFile.add(new JNPadMenuItem(actions.saveFileAsAction));
    mFile.add(new JNPadMenuItem(actions.saveAllFilesAction));

    mFile.addSeparator();
    mFile.add(new JNPadMenuItem(actions.fileBrowserAction));
    mFile.add(new JNPadMenuItem(actions.filePropertiesAction));
    mFile.addSeparator();

    mFile.add(new JNPadMenuItem(actions.printSetAction));
    mFile.add(new JNPadMenuItem(actions.printAction));

    mFile.addSeparator();
    mFile.add(new JNPadMenuItem(actions.reloadAction));
    mFile.add(new JNPadMenuItem(actions.executeActionAction));
    mFile.addSeparator();

    mFile.add(new JNPadMenuItem(actions.loadSessionAction));
    mFile.add(new JNPadMenuItem(actions.saveSessionAction));
    
    mFile.addSeparator();
    if(SystemTray.isSupported()) 
      mFile.add(new JNPadMenuItem(actions.reduceAsTrayIconAction));
    mFile.add(new JNPadMenuItem(actions.restartAction));

    mFile.addSeparator();

    mFile.add(new JNPadMenuItem(actions.exitAction));

    if (Config.isDefaultMode()) {
      btRecentFiles.setToolTipText(mFileRecentFiles.getText());
      btRecentFiles.setIcon(mFileRecentFiles.getIcon());
    }
    
    return mFile;
  }

  /**
   * Creates the edit menu.
   *
   * @param actions the actions
   * @return the menu
   */
  private JMenu createEditMenu(final JNPadActionHelper actions) {
    JMenu mEdit = GUIUtilities.createMenu(JNPadBundle.getString("menu.edit"), null); //$NON-NLS-1$

    mEdit.add(new JNPadMenuItem(actions.undoAction));
    mEdit.add(new JNPadMenuItem(actions.redoAction));
    mEdit.addSeparator();
    mEdit.add(new JNPadMenuItem(actions.cutAction));
    mEdit.add(new JNPadMenuItem(actions.cutLineAction));
    mEdit.add(new JNPadMenuItem(actions.copyAction));
    mEdit.add(new JNPadMenuItem(actions.copyLineAction));
    mEdit.add(new JNPadMenuItem(actions.pasteAction));
    mEdit.addSeparator();
    mEdit.add(new JNPadMenuItem(actions.selectAllAction));

    JMenu mEditSelectParagraph = GUIUtilities.createMenu(JNPadBundle.getString("menu.edit.selectParagraph"), GUIUtilities.EMPTY_ICON);  //$NON-NLS-1$
    mEditSelectParagraph.add(new JNPadMenuItem(actions.selectParagraphAction));
    mEditSelectParagraph.add(new JNPadMenuItem(actions.selectionBeginParagraphAction));
    mEditSelectParagraph.add(new JNPadMenuItem(actions.selectionEndParagraphAction));
    mEdit.add(mEditSelectParagraph);

    JMenu mEditSelectLine = GUIUtilities.createMenu(JNPadBundle.getString("menu.edit.selectLine"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    mEditSelectLine.add(new JNPadMenuItem(actions.selectLineAction));
    mEditSelectLine.add(new JNPadMenuItem(actions.selectionBeginLineAction));
    mEditSelectLine.add(new JNPadMenuItem(actions.selectionEndLineAction));
    mEdit.add(mEditSelectLine);

    mEdit.add(new JNPadMenuItem(actions.selectWordAction));

    mEdit.addSeparator();

    mEdit.add(new JNPadMenuItem(actions.deleteAction));

    JMenu mEditDeleteParagraph = GUIUtilities.createMenu(JNPadBundle.getString("menu.edit.deleteParagraph"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    mEditDeleteParagraph.add(new JNPadMenuItem(actions.deleteParagraphAction));
    mEditDeleteParagraph.add(new JNPadMenuItem(actions.deletionBeginParagraphAction));
    mEditDeleteParagraph.add(new JNPadMenuItem(actions.deletionEndParagraphAction));
    mEdit.add(mEditDeleteParagraph);

    JMenu mEditDeletetLine = GUIUtilities.createMenu(JNPadBundle.getString("menu.edit.deleteLine"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    mEditDeletetLine.add(new JNPadMenuItem(actions.deleteLineAction));
    mEditDeletetLine.add(new JNPadMenuItem(actions.deletionBeginLineAction));
    mEditDeletetLine.add(new JNPadMenuItem(actions.deletionEndLineAction));
    mEdit.add(mEditDeletetLine);

    mEdit.add(new JNPadMenuItem(actions.deleteWordAction));

    mEdit.addSeparator();

    JMenu mEditionText = GUIUtilities.createMenu(JNPadBundle.getString("menu.edit.text"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    mEditionText.add(new JNPadMenuItem(actions.tabsToSpacesAction));
    mEditionText.add(new JNPadMenuItem(actions.spacesToTabsAction));
    mEditionText.addSeparator();
    mEditionText.add(new JNPadMenuItem(actions.beginLinesAction));
    mEditionText.add(new JNPadMenuItem(actions.endLinesAction));
    mEditionText.addSeparator();
    mEditionText.add(new JNPadMenuItem(actions.duplicateCurrentLineAction));
    mEditionText.add(new JNPadMenuItem(actions.joinLinesAction));
    mEditionText.add(new JNPadMenuItem(actions.sortLinesAscendingAction));
    mEditionText.add(new JNPadMenuItem(actions.sortLinesDescendingAction));
    mEditionText.add(new JNPadMenuItem(actions.removeEndSpacesAction));
    mEditionText.add(new JNPadMenuItem(actions.removeEmptyLinesAction));
    mEditionText.addSeparator();
    mEditionText.add(new JNPadMenuItem(actions.completeWordAction));
    mEditionText.add(new JNPadMenuItem(actions.completeWordAllAction));
    mEditionText.add(new JNPadMenuItem(actions.wordCountAction));
    mEdit.add(mEditionText);
    JMenu mEditionFile = GUIUtilities.createMenu(JNPadBundle.getString("menu.edit.file"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    mEditionFile.add(new JNPadMenuItem(actions.insertFileExtensionAction));
    mEditionFile.add(new JNPadMenuItem(actions.insertFileFullNameAction));
    mEditionFile.add(new JNPadMenuItem(actions.insertFileNameAction));
    mEditionFile.addSeparator();
    mEditionFile.add(new JNPadMenuItem(actions.insertFileFullPathAction));
    mEditionFile.add(new JNPadMenuItem(actions.insertFilePathAction));
    mEdit.add(mEditionFile);
    mEdit.add(new JNPadMenuItem(actions.insertDateAction));

    return mEdit;
  }

  /**
   * Creates the search menu.
   *
   * @param actions the actions
   * @return the menu
   */
  private JMenu createSearchMenu(final JNPadActionHelper actions) {
    JMenu mSearch = GUIUtilities.createMenu(JNPadBundle.getString("menu.search"), null); //$NON-NLS-1$

    mSearch.add(new JNPadMenuItem(actions.findAction));
    mSearch.add(new JNPadMenuItem(actions.findNextAction));
    mSearch.add(new JNPadMenuItem(actions.findPreviousAction));
    mSearch.add(new JNPadMenuItem(actions.replaceAction));
    mSearch.add(new JNPadMenuItem(actions.replaceNextAction));
    mSearch.add(new JNPadMenuItem(actions.incrementalSearchAction));
    mSearch.addSeparator();
    mSearch.add(new JNPadMenuItem(actions.highlightAllOccurrencesAction));
    mSearch.add(new JNPadMenuItem(actions.clearAllOccurrencesAction));
    mSearch.add(new JNPadMenuItem(actions.nextOccurrenceAction));
    mSearch.add(new JNPadMenuItem(actions.previousOccurrenceAction));
    mSearch.add(new JNPadMenuItem(actions.goToLineAction));
    mSearch.addSeparator();
    mSearch.add(new JNPadMenuItem(actions.nextBookmarkAction));
    mSearch.add(new JNPadMenuItem(actions.previousBookmarkAction));
    mSearch.add(new JNPadMenuItem(actions.toggleBookmarkAction));
    mSearch.add(new JNPadMenuItem(actions.clearAllBookmarksAction));

    return mSearch;
  }

  /**
   * Creates the view menu.
   *
   * @param actions the actions
   * @return the menu
   */
  private JMenu createViewMenu(final JNPadActionHelper actions) {
    JMenu mView = GUIUtilities.createMenu(JNPadBundle.getString("menu.view"), null); //$NON-NLS-1$

    if (Config.isDefaultMode() || Config.isBasicMode()) {
      JMenu mViewToolbars = GUIUtilities.createMenu(JNPadBundle.getString("menu.view.toolbars"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
      mViewToolbars.add(new JNPadCheckBoxMenuItem(actions.toolBarVisibleAction));
      mViewToolbars.addSeparator();
      mViewToolbars.add(new JNPadCheckBoxMenuItem(actions.toolbarsFileAction));
      mViewToolbars.add(new JNPadCheckBoxMenuItem(actions.toolbarsEditRecantationAction));
      mViewToolbars.add(new JNPadCheckBoxMenuItem(actions.toolbarsEditClipboardAction));
      if (Config.isDefaultMode()) {
        mViewToolbars.add(new JNPadCheckBoxMenuItem(actions.toolbarsEditSelectionAction));
        mViewToolbars.add(new JNPadCheckBoxMenuItem(actions.toolbarsEditDeletionAction));
      }
      mViewToolbars.add(new JNPadCheckBoxMenuItem(actions.toolbarsSearchAction));
      if (Config.isDefaultMode()) {
        mViewToolbars.add(new JNPadCheckBoxMenuItem(actions.toolbarsViewAction));
        mViewToolbars.add(new JNPadCheckBoxMenuItem(actions.toolbarsFormatAction));
      }
      mViewToolbars.add(new JNPadCheckBoxMenuItem(actions.toolbarsWindowAction));
      mViewToolbars.addSeparator();
      mViewToolbars.add(new JNPadMenuItem(actions.toolbarsAllVisibleAction));
      mViewToolbars.add(new JNPadMenuItem(actions.toolbarsNoneVisibleAction));
      mView.add(mViewToolbars);
    }

    mView.add(new JNPadCheckBoxMenuItem(actions.findResultsVisibleAction));
    mView.add(new JNPadCheckBoxMenuItem(actions.statusBarVisibleAction));
    mView.addSeparator();

    mView.add(new JNPadCheckBoxMenuItem(actions.lineWrapAction));
    mView.add(new JNPadCheckBoxMenuItem(actions.lineNumbersAction));
    mView.add(new JNPadCheckBoxMenuItem(actions.activeLineAction));
    mView.add(new JNPadCheckBoxMenuItem(actions.rightMarginLineAction));
    mView.add(new JNPadCheckBoxMenuItem(actions.markStripAction));
    mView.add(new JNPadCheckBoxMenuItem(actions.markOccurrencesAction));
    mView.add(new JNPadCheckBoxMenuItem(actions.markBracketsAction));
    mView.add(new JNPadMenuItem(actions.focusOnMainViewAction));
    ButtonGroup bgScope = new ButtonGroup();
    JMenu mScope = GUIUtilities.createMenu(JNPadBundle.getString("menu.view.scope"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    mScope.add(new JNPadCheckBoxMenuItem(actions.selectScopeAsViewerAction, bgScope));
    mScope.add(new JNPadCheckBoxMenuItem(actions.selectScopeAsBufferSetAction, bgScope));
    mScope.add(new JNPadCheckBoxMenuItem(actions.selectScopeAsBufferAction, bgScope));
    mScope.add(new JNPadCheckBoxMenuItem(actions.selectScopeAsEditPaneAction, bgScope));
    mView.add(mScope);
    mView.addSeparator();
    mView.add(new JNPadMenuItem(actions.fullScreenAction));

    return mView;
  }

  /**
   * Creates the format menu.
   *
   * @param actions the actions
   * @return the menu
   */
  private JMenu createFormatMenu(final JNPadActionHelper actions) {
    JMenu mFormat = GUIUtilities.createMenu(JNPadBundle.getString("menu.format"), null); //$NON-NLS-1$

    JMenu mEOL = GUIUtilities.createMenu(JNPadBundle.getString("menu.format.eol"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    mEOL.add(new JNPadCheckBoxMenuItem(actions.selectEOLAsDOSAction, bgEOL));
    mEOL.add(new JNPadCheckBoxMenuItem(actions.selectEOLAsUnixAction, bgEOL));
    mEOL.add(new JNPadCheckBoxMenuItem(actions.selectEOLAsMacAction, bgEOL));
    mFormat.add(mEOL);

    MnemonicHelper mnemonicHelper = new MnemonicHelper();

    JMenu mEncoding = GUIUtilities.createMenu(JNPadBundle.getString("menu.format.encoding"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    mnemonicHelper.clear();
    Set<String> set = GUIUtilities.getCharsetTreeSet();
    for (String encoding : set) {
      mEncoding.add(new JNPadRadioButtonMenuItem(new SelectEncodingAction(jNPad, encoding, mnemonicHelper), bgEncoding));
    }
    mFormat.add(mEncoding);

    mFormat.addSeparator();

    mFormat.add(new JNPadMenuItem(actions.rightIndentAction));
    mFormat.add(new JNPadMenuItem(actions.leftIndentAction));

    mFormat.addSeparator();

    mFormat.add(new JNPadMenuItem(actions.toUpperCaseAction));
    mFormat.add(new JNPadMenuItem(actions.toLowerCaseAction));
    mFormat.add(new JNPadMenuItem(actions.invertUpperLowerAction));
    mFormat.add(new JNPadMenuItem(actions.capitalizeAction));
    mFormat.add(new JNPadMenuItem(actions.toTitleAction));

    mFormat.addSeparator();
    mFormat.add(new JNPadCheckBoxMenuItem(actions.setReadOnlyAction));
    JMenu mAlignStrings = GUIUtilities.createMenu(JNPadBundle.getString("menu.format.alignStrings"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    mAlignStrings.add(new JNPadMenuItem(actions.alignStringsByCommaAction));
    mAlignStrings.add(new JNPadMenuItem(actions.alignStringsByEqualAction));
    mAlignStrings.add(new JNPadMenuItem(actions.alignStringsByClipboardAction));
    mFormat.add(mAlignStrings);
    mFormat.addSeparator();

    mFormat.add(new JNPadMenuItem(actions.increaseFontAction));
    mFormat.add(new JNPadMenuItem(actions.decreaseFontAction));

    return mFormat;
  }

  /**
   * Creates the configure menu.
   *
   * @param actions the actions
   * @return the menu
   */
  private JMenu createConfigureMenu(final JNPadActionHelper actions) {
    JMenu mConfigure = GUIUtilities.createMenu(JNPadBundle.getString("menu.configure"), null); //$NON-NLS-1$

    JMenu mLanguage = GUIUtilities.createMenu(JNPadBundle.getString("menu.configure.language"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    ButtonGroup bgLanguage = new ButtonGroup();
    String language = Config.getLocale().getLanguage();
    mLanguage.add(new JNPadRadioButtonMenuItem(new SelectLanguageAction(jNPad, JNPadBundle.getString("menu.configure.language.en"), "en", "en".equals(language)), bgLanguage)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    mLanguage.add(new JNPadRadioButtonMenuItem(new SelectLanguageAction(jNPad, JNPadBundle.getString("menu.configure.language.es"), "es", "es".equals(language)), bgLanguage)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    mConfigure.add(mLanguage);

    JMenu mMode = GUIUtilities.createMenu(JNPadBundle.getString("menu.configure.mode"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    ButtonGroup bgMode = new ButtonGroup();
    mMode.add(new JNPadRadioButtonMenuItem(new SelectModeAction(jNPad, Mode.DEFAULT)         , bgMode));
    mMode.add(new JNPadRadioButtonMenuItem(new SelectModeAction(jNPad, Mode.BASIC)           , bgMode));
    mMode.add(new JNPadRadioButtonMenuItem(new SelectModeAction(jNPad, Mode.MINIMALIST)      , bgMode));
    mMode.add(new JNPadRadioButtonMenuItem(new SelectModeAction(jNPad, Mode.DISTRACTION_FREE), bgMode));
    mConfigure.add(mMode);

    mConfigure.addSeparator();
    JMenu mAutoCompletion = GUIUtilities.createMenu(JNPadBundle.getString("menu.configure.autoCompletion"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    mAutoCompletion.add(new JNPadCheckBoxMenuItem(actions.autoCompletionAction));
    mAutoCompletion.addSeparator();
    ButtonGroup bgAutoCompletion = new ButtonGroup();
    final int trigger = Config.TEXT_AUTOCOMPLETION_TRIGGER.getValue();
    for(int nth = 1; nth < 10; nth++) {
      mAutoCompletion.add(new JNPadRadioButtonMenuItem(new SelectAutoCompletionFromNthAction(jNPad, nth, nth == trigger), bgAutoCompletion));
    }
    mConfigure.add(mAutoCompletion);

    mConfigure.addSeparator();
    JMenu mIndentation = GUIUtilities.createMenu(JNPadBundle.getString("menu.configure.indentation"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    mIndentation.add(new JNPadCheckBoxMenuItem(actions.autoIndentAction));
    mIndentation.add(new JNPadCheckBoxMenuItem(actions.indentUsingSpacesAction));
    mIndentation.addSeparator();
    ButtonGroup bgIndentation = new ButtonGroup();
    final int tabSize = Config.TEXT_TAB_SIZE.getValue();
    for (int size = 1; size < 9; size++) {
      mIndentation.add(new JNPadRadioButtonMenuItem(new SelectTabSizeAction(jNPad, size, size == tabSize), bgIndentation));
    }
    mConfigure.add(mIndentation);

    mConfigure.addSeparator();

    mConfigure.add(new JNPadMenuItem(actions.loadOptionsFileAction));
    mConfigure.add(new JNPadMenuItem(actions.loadDefaultOptionsFileAction));
    mConfigure.add(new JNPadMenuItem(actions.loadShortcutsFileAction));
    mConfigure.add(new JNPadMenuItem(actions.loadLoggingConfigFileAction));

    mConfigure.addSeparator();

    JMenu mFonts = GUIUtilities.createMenu(JNPadBundle.getString("menu.configure.fonts"), GUIUtilities.loadIcon("fonts.png")); //$NON-NLS-1$ //$NON-NLS-2$
    mFonts.add(new JNPadMenuItem(actions.fontsAction));
    mFonts.addSeparator();
    ButtonGroup bgFontSize = new ButtonGroup();
    mFonts.add(new JNPadRadioButtonMenuItem(new SelectFontSizeAction(jNPad, FontSize.TINY)  , bgFontSize));
    mFonts.add(new JNPadRadioButtonMenuItem(new SelectFontSizeAction(jNPad, FontSize.SMALL) , bgFontSize));
    mFonts.add(new JNPadRadioButtonMenuItem(new SelectFontSizeAction(jNPad, FontSize.NORMAL), bgFontSize));
    mFonts.add(new JNPadRadioButtonMenuItem(new SelectFontSizeAction(jNPad, FontSize.LARGE) , bgFontSize));
    mFonts.add(new JNPadRadioButtonMenuItem(new SelectFontSizeAction(jNPad, FontSize.HUGE)  , bgFontSize));
    mFonts.addSeparator();
    mFonts.add(new JNPadMenuItem(actions.resetFontAction));
    mConfigure.add(mFonts);
    JMenu mForeground = GUIUtilities.createMenu(JNPadBundle.getString("menu.configure.foreground"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    mForeground.add(new JNPadMenuItem(actions.foregroundAction));
    mForeground.addSeparator();
    mForeground.add(new JNPadMenuItem(actions.brightenForegroundAction));
    mForeground.add(new JNPadMenuItem(actions.darkenForegroundAction));
    mForeground.addSeparator();
    mForeground.add(new JNPadMenuItem(actions.resetForegroundAction));
    mConfigure.add(mForeground);
    JMenu mBackground = GUIUtilities.createMenu(JNPadBundle.getString("menu.configure.background"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    mBackground.add(new JNPadMenuItem(actions.backgroundAction));
    mBackground.addSeparator();
    mBackground.add(new JNPadMenuItem(actions.brightenBackgroundAction));
    mBackground.add(new JNPadMenuItem(actions.darkenBackgroundAction));
    mBackground.addSeparator();
    mBackground.add(new JNPadMenuItem(actions.resetBackgroundAction));
    mConfigure.add(mBackground);

    mConfigure.addSeparator();

    JMenu mColorScheme = GUIUtilities.createMenu(JNPadBundle.getString("menu.configure.colorscheme"), GUIUtilities.loadIcon("colorscheme.png")); //$NON-NLS-1$ //$NON-NLS-2$
    String colorscheme = Config.JNPAD_COLORSCHEME.getValue();
    File f = new File(Config.COLORSCHEMES_DIR);
    File[] fs = f.listFiles();
    if (fs.length > 0) {
      MnemonicHelper mnemonicHelper = new MnemonicHelper();
      for (File f1 : fs) {
        String baseName = Utilities.getFileBaseName(f1.getPath());
        mColorScheme.add(new JNPadRadioButtonMenuItem(new SelectColorSchemeAction(jNPad, f1, colorscheme.equalsIgnoreCase(baseName), mnemonicHelper), bgColorScheme));
      }
    }
    mConfigure.add(mColorScheme);

    JMenu mKeymap = GUIUtilities.createMenu(JNPadBundle.getString("menu.configure.keymap"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    ButtonGroup bgKeymap = new ButtonGroup();
    String keymap = Config.JNPAD_KEYMAP.getValue();
    f = new File(Config.KEYMAP_DIR);
    fs = f.listFiles();
    if (fs.length > 0) {
      MnemonicHelper mnemonicHelper = new MnemonicHelper();
      for (File f1 : fs) {
        String baseName = Utilities.getFileBaseName(f1.getPath());
        mKeymap.add(new JNPadRadioButtonMenuItem(new SelectKeymapAction(jNPad, f1, keymap.equalsIgnoreCase(baseName), mnemonicHelper), bgKeymap));
      }
    }
    mConfigure.add(mKeymap);

    JMenu mLookAndFeel = GUIUtilities.createMenu(JNPadBundle.getString("menu.configure.laf"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    ButtonGroup bgLookAndFeel = new ButtonGroup();
    String laf_key = LAFUtils.getCurrentLAFKey();
    MnemonicHelper mnemonicHelper = new MnemonicHelper();
    mLookAndFeel.add(new JNPadRadioButtonMenuItem(new SelectLAFAction(jNPad, "jNPad (Light)", LAFUtils.LAF_KEY_JNPAD_LIGHT, LAFUtils.LAF_KEY_JNPAD_LIGHT.equals(laf_key), mnemonicHelper), bgLookAndFeel)); //$NON-NLS-1$
    mLookAndFeel.add(new JNPadRadioButtonMenuItem(new SelectLAFAction(jNPad, "jNPad (Dark)" , LAFUtils.LAF_KEY_JNPAD_DARK , LAFUtils.LAF_KEY_JNPAD_DARK.equals(laf_key) , mnemonicHelper), bgLookAndFeel)); //$NON-NLS-1$
    mLookAndFeel.add(new JNPadRadioButtonMenuItem(new SelectLAFAction(jNPad, "Ocean2"       , LAFUtils.LAF_KEY_OCEAN2     , LAFUtils.LAF_KEY_OCEAN2.equals(laf_key)     , mnemonicHelper), bgLookAndFeel)); //$NON-NLS-1$
    mLookAndFeel.add(new JNPadRadioButtonMenuItem(new SelectLAFAction(jNPad, "Steel"        , LAFUtils.LAF_KEY_STEEL      , LAFUtils.LAF_KEY_STEEL.equals(laf_key)      , mnemonicHelper), bgLookAndFeel)); //$NON-NLS-1$
    mLookAndFeel.addSeparator();
    UIManager.LookAndFeelInfo[] lafis = UIManager.getInstalledLookAndFeels();
    for (UIManager.LookAndFeelInfo lafi : lafis) {
      boolean b = laf_key.equals(lafi.getClassName());
      mLookAndFeel.add(new JNPadRadioButtonMenuItem(new SelectLAFAction(jNPad, lafi, b, mnemonicHelper), bgLookAndFeel));
    }
    mLookAndFeel.addSeparator();
    mLookAndFeel.add(new JNPadRadioButtonMenuItem(new SelectLAFAction(jNPad, JNPadBundle.getString("menu.configure.laf.system"), LAFUtils.LAF_KEY_NATIVE, LAFUtils.LAF_KEY_NATIVE.equals(laf_key), mnemonicHelper), bgLookAndFeel)); //$NON-NLS-1$
    mLookAndFeel.add(new JNPadRadioButtonMenuItem(new SelectLAFAction(jNPad, JNPadBundle.getString("menu.configure.laf.java"), LAFUtils.LAF_KEY_JAVA, LAFUtils.LAF_KEY_JAVA.equals(laf_key), mnemonicHelper), bgLookAndFeel)); //$NON-NLS-1$

    mConfigure.add(mLookAndFeel);

    return mConfigure;
  }

  /**
   * Creates the window menu.
   *
   * @param actions the actions
   * @return the menu
   */
  private JMenu createWindowMenu(final JNPadActionHelper actions) {
    GUIUtilities.setLocalizedText(mWindow, JNPadBundle.getString("menu.window")); //$NON-NLS-1$

    mWindow.add(new JNPadMenuItem(actions.windowsAction));
    mWindow.addSeparator();
    mWindow.add(new JNPadMenuItem(actions.previousBufferAction));
    mWindow.add(new JNPadMenuItem(actions.nextBufferAction));
    mWindow.addSeparator();
    JMenu mSplitting = GUIUtilities.createMenu(JNPadBundle.getString("menu.window.splitting"), GUIUtilities.EMPTY_ICON); //$NON-NLS-1$
    mSplitting.add(new JNPadMenuItem(actions.unsplitCurrentAction));
    mSplitting.add(new JNPadMenuItem(actions.unsplitAction));
    mSplitting.add(new JNPadMenuItem(actions.splitHorizontallyAction));
    mSplitting.add(new JNPadMenuItem(actions.splitVerticallyAction));
    mSplitting.add(new JNPadMenuItem(actions.restoreSplitAction));
    mSplitting.addSeparator();
    mSplitting.add(new JNPadMenuItem(actions.previousEditPaneAction));
    mSplitting.add(new JNPadMenuItem(actions.nextEditPaneAction));
    mSplitting.addSeparator();
    mSplitting.add(new JNPadMenuItem(actions.unsplitViewerCurrentAction));
    mSplitting.add(new JNPadMenuItem(actions.unsplitViewerAction));
    mSplitting.add(new JNPadMenuItem(actions.splitViewerHorizontallyAction));
    mSplitting.add(new JNPadMenuItem(actions.splitViewerVerticallyAction));
    mSplitting.add(new JNPadMenuItem(actions.restoreViewerSplitAction));
    mSplitting.addSeparator();
    mSplitting.add(new JNPadMenuItem(actions.previousBufferSetAction));
    mSplitting.add(new JNPadMenuItem(actions.nextBufferSetAction));
    mWindow.add(mSplitting);

    mWindow.addSeparator();

    return mWindow;
  }
  
  /**
   * Creates the help menu.
   *
   * @param actions the actions
   * @return the menu
   */
  private JMenu createHelpMenu(final JNPadActionHelper actions) {
    JMenu mHelp = GUIUtilities.createMenu(JNPadBundle.getString("menu.help"), null); //$NON-NLS-1$
    mHelp.add(new JNPadMenuItem(actions.cliArgsAction));
    mHelp.add(new JNPadMenuItem(actions.licenceAction));
    mHelp.addSeparator();
    mHelp.add(new JNPadMenuItem(actions.check4UpdatesAction));
    mHelp.addSeparator();
    mHelp.add(new JNPadMenuItem(actions.aboutAction));
    return mHelp;
  }

  /**
   * Creates the tabbed popup menu.
   *
   * @return the popup menu
   */
  JPopupMenu createTabbedPopupMenu() {
    final JNPadActionHelper actions = jNPad.actions;

    JPopupMenu popupMenu = new JPopupMenu();
    popupMenu.add(new JNPadMenuItem(actions.saveFileAction));
    popupMenu.add(new JNPadMenuItem(actions.saveFileAsAction));
    popupMenu.add(new JNPadMenuItem(actions.saveAllFilesAction));
    popupMenu.addSeparator();
    popupMenu.add(new JNPadMenuItem(actions.closeFileAction));
    popupMenu.add(new JNPadMenuItem(actions.closeFilesAction));
    popupMenu.add(new JNPadMenuItem(actions.closeAllAction));
    popupMenu.add(new JNPadMenuItem(actions.closeOtherAction));
    popupMenu.add(new JNPadMenuItem(actions.closeAllToLeftAction));
    popupMenu.add(new JNPadMenuItem(actions.closeAllToRightAction));
    popupMenu.addSeparator();
    popupMenu.add(new JNPadMenuItem(actions.printAction));
    popupMenu.addSeparator();
    popupMenu.add(new JNPadMenuItem(actions.reloadAction));

    SwingUtilities.updateComponentTreeUI(popupMenu);
    popupMenu.pack();
    return popupMenu;
  }

  /**
   * Creates the encoding popup menu.
   *
   * @return the popup menu
   */
  JPopupMenu createEncodingPopupMenu() {
    JPopupMenu popupMenu = new JPopupMenu();
    for (Enumeration<AbstractButton> e = bgEncoding.getElements(); e.hasMoreElements();) {
      AbstractButton b = e.nextElement();
      Action a = b.getAction();
      if (a != null) {
        popupMenu.add(new JNPadRadioButtonMenuItem(a));
      }
    }
    SwingUtilities.updateComponentTreeUI(popupMenu);
    popupMenu.pack();
    return popupMenu;
  }

  /**
   * Gets the menu file re open path.
   *
   * @param path the path
   * @return the menu file re open path
   */
  String getMenuFileReOpenPath(String path) {
    return GUIUtilities.getFilePath(jNPad.getFontMetrics(mFileRecentFiles.getFont()),
                                    path,
                                    GUIUtilities.getScreenDimension().width / 3);
  }

  /**
   * Load recent files.
   */
  void loadRecentFiles() {
    final JNPadActionHelper actions = jNPad.actions;

    mFileRecentFiles.removeAll();
    pmRecentFiles.removeAll();

    List<JNPadInput> l = Config.getJNPadInputListProp("files.recent"); //$NON-NLS-1$

    if (l.size() > 0) {
      for (int i = 0; i < l.size(); i++) {
        JNPadInput in = l.get(i);
        String path = i + "  " + getMenuFileReOpenPath(in.getPath()); //$NON-NLS-1$

        Action action = new OpenRecentFileAction(jNPad, in);

        JMenuItem mi1 = new JMenuItem(action);
        mi1.setText(path);
        mFileRecentFiles.add(mi1);

        JMenuItem mi2 = new JMenuItem(action);
        mi2.setText(path);
        pmRecentFiles.add(mi2);
      }
    }
    else {
      mFileRecentFiles.setEnabled(false);
      actions.openAllRecentFilesAction.setEnabled(false);
      actions.emptyRecentFilesListAction.setEnabled(false);
      btRecentFiles.setEnabled(false);
    }

    pmRecentFiles.addSeparator();
    pmRecentFiles.add(new JNPadMenuItem(actions.openAllRecentFilesAction));
    pmRecentFiles.add(new JNPadMenuItem(actions.emptyRecentFilesListAction));
    btRecentFiles.setPopupMenu(pmRecentFiles);

    GUIUtilities.setMnemonic(mFileRecentFiles, new MnemonicHelper(), false);
  }

  /**
   * Open all recent files.
   */
  void openAllRecentFiles() {
    Component[] components = mFileRecentFiles.getMenuComponents();
    for (Component component : components) {
      JMenuItem mi = (JMenuItem) component;
      Action action = mi.getAction();
      if (action != null && action instanceof OpenRecentFileAction) {
        action.actionPerformed(null);
      }
      else {
        jNPad.openFile(mi.getToolTipText());
      }
    }
  }

  /**
   * Empty recent files list.
   */
  void emptyRecentFilesList() {
    final JNPadActionHelper actions = jNPad.actions;

    mFileRecentFiles.removeAll();
    pmRecentFiles.removeAll();

    mFileRecentFiles.setEnabled(false);
    actions.openAllRecentFilesAction.setEnabled(false);
    actions.emptyRecentFilesListAction.setEnabled(false);
    btRecentFiles.setEnabled(false);

    Config.remove("files.recent"); //$NON-NLS-1$
  }
  
  /**
   * Update recent files.
   *
   * @param path the path
   * @param cursorPosition the cursor position
   * @param isReadOnly is read only
   * @param splitConfig the split config
   * @param isLineWrapped is line wrapped
   */
  void updateRecentFiles(String path, int cursorPosition, boolean isReadOnly, String splitConfig, boolean isLineWrapped) {
    File file = new File(path);
    if (!file.isFile()) {
      return;
    }

    final JNPadActionHelper actions = jNPad.actions;

    boolean b = false;

    List<JNPadInput> l = Config.getJNPadInputListProp("files.recent"); //$NON-NLS-1$

    for (int i = 0; !b && i < l.size(); i++) {
      JNPadInput in = l.get(i);
      if (in.getPath().equals(path)) {
        l.remove(i);
        b = true;
      }
    }

    JNPadInput in = new JNPadInput(path, cursorPosition, isReadOnly, false, splitConfig, isLineWrapped);

    l.add(0, in);

    final int max_elements = Config.FILES_RECENT_MAX.getValue();

    if (l.size() > max_elements)
      Utilities.restrictListSize(l, max_elements);

    Config.setJNPadInputListProp("files.recent", l); //$NON-NLS-1$

    Component[] components = mFileRecentFiles.getMenuComponents();

    String text = getMenuFileReOpenPath(path);

    Action action = new OpenRecentFileAction(jNPad, in);

    JMenuItem mi1 = new JMenuItem(action);
    mi1.setText(text);

    JMenuItem mi2 = new JMenuItem(action);
    mi2.setText(text);

    boolean add = true;
    for (int i = 0; i < components.length; i++) {
      if (((JMenuItem) components[i]).getToolTipText().equals(path)) {
        mFileRecentFiles.remove(i);
        mFileRecentFiles.insert(mi1, 0);
        pmRecentFiles.remove(i);
        pmRecentFiles.insert(mi2, 0);
        add = false;
        break;
      }
    }
    if (add) {
      mFileRecentFiles.add(mi1, 0);
      pmRecentFiles.add(mi2, 0);
      if (components.length > max_elements) {
        mFileRecentFiles.remove(components.length - 1);
        pmRecentFiles.remove(components.length - 1);
      }
    }

    renameMenuRecentFiles();

    b = mFileRecentFiles.getMenuComponentCount() > 0;
    mFileRecentFiles.setEnabled(b);
    actions.openAllRecentFilesAction.setEnabled(b);
    actions.emptyRecentFilesListAction.setEnabled(b);
    btRecentFiles.setEnabled(b);
  }

  /**
   * Rename menu recent files.
   */
  private void renameMenuRecentFiles() {
    Component[] components = mFileRecentFiles.getMenuComponents();
    for (int i = 0; i < components.length; i++) {
      String s = ((JMenuItem) components[i]).getToolTipText();
      String t = i + "  " + getMenuFileReOpenPath(s); //$NON-NLS-1$
      ((JMenuItem) components[i]).setText(t);
      ((JMenuItem) pmRecentFiles.getComponent(i)).setText(t);
    }
    GUIUtilities.setMnemonic(mFileRecentFiles, new MnemonicHelper(), false);
  }

  //////////////////////////////////////////////////////////////////////////////
  /**
   * The Class CloseLabel.
   */
  private class CloseLabel extends JLabel {
    /** UID */
    private static final long serialVersionUID = 1624209664888436368L;

    /**
     * Instantiates a new close label.
     */
    CloseLabel() {
      super(" X "); //$NON-NLS-1$
      setOpaque(false);
      setBorder(GUIUtilities.createEmptyBorder(5, 1));
      addMouseListener(new MouseAdapter() {
        @Override
        public void mouseEntered(MouseEvent e) {
          setOpaque(true);
          setBackground(LAFUtils.getMenuSelectionBackground());
          setForeground(LAFUtils.getMenuSelectionForeground());
        }

        @Override
        public void mouseExited(MouseEvent e) {
          setOpaque(false);
          setBackground(LAFUtils.getLabelBackground());
          setForeground(LAFUtils.getLabelForeground());
        }

        @Override
        public void mouseClicked(MouseEvent e) {
          jNPad.closeFile(null, true);
        }
      });
    }
  }
  //////////////////////////////////////////////////////////////////////////////
  
}

