Package org.pentaho.reporting.tools.configeditor

Source Code of org.pentaho.reporting.tools.configeditor.ConfigDescriptionEditor$CancelAction

/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* 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 Lesser General Public License for more details.
*
* Copyright (c) 2001 - 2009 Object Refinery Ltd, Pentaho Corporation and Contributors.  All rights reserved.
*/

package org.pentaho.reporting.tools.configeditor;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.MessageFormat;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.ScrollPaneConstants;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.reporting.libraries.base.boot.AbstractBoot;
import org.pentaho.reporting.libraries.base.config.Configuration;
import org.pentaho.reporting.libraries.base.util.FilesystemFilter;
import org.pentaho.reporting.libraries.base.util.ObjectUtilities;
import org.pentaho.reporting.libraries.base.util.ResourceBundleSupport;
import org.pentaho.reporting.libraries.xmlns.common.ParserUtil;
import org.pentaho.reporting.tools.configeditor.model.ClassConfigDescriptionEntry;
import org.pentaho.reporting.tools.configeditor.model.ConfigDescriptionEntry;
import org.pentaho.reporting.tools.configeditor.model.ConfigDescriptionModel;
import org.pentaho.reporting.tools.configeditor.model.EnumConfigDescriptionEntry;
import org.pentaho.reporting.tools.configeditor.model.TextConfigDescriptionEntry;

/**
* The config description editor is used to edit the configuration metadata used in the ConfigEditor to describe the
* ReportConfiguration keys.
*
* @author Thomas Morgner
*/
public class ConfigDescriptionEditor extends JFrame
{
  private static final Log logger = LogFactory.getLog(ConfigDescriptionEditor.class);

  private class CloseHandler extends WindowAdapter
  {

    private CloseHandler()
    {
    }

    /**
     * Invoked when a window is in the process of being closed. The close operation can be overridden at this point.
     */
    public void windowClosing(final WindowEvent e)
    {
      attempExit();
    }
  }

  /**
   * A configuration key to define the Font used in the editor.
   */
  protected static final String EDITOR_FONT_KEY = "org.pentaho.reporting.engine.classic.core.modules.gui.config.EditorFont"; //$NON-NLS-1$
  /**
   * A configuration key to define the Font size used in the editor.
   */
  protected static final String EDITOR_FONT_SIZE_KEY = "org.pentaho.reporting.engine.classic.core.modules.gui.config.EditorFontSize"; //$NON-NLS-1$

  /**
   * An internal constant to activate the class detail editor.
   */
  private static final String CLASS_DETAIL_EDITOR_NAME = "Class"; //$NON-NLS-1$
  /**
   * An internal constant to activate the enumeration detail editor.
   */
  private static final String ENUM_DETAIL_EDITOR_NAME = "Enum"; //$NON-NLS-1$
  /**
   * An internal constant to activate the text detail editor.
   */
  private static final String TEXT_DETAIL_EDITOR_NAME = "Text"; //$NON-NLS-1$

  /**
   * Handles close requests in this editor.
   */
  private class CloseAction extends AbstractAction
  {
    /**
     * Defaultconstructor.
     */
    private CloseAction()
    {
      putValue(Action.NAME, getResources().getString("action.exit.name")); //$NON-NLS-1$
    }

    /**
     * Handles the close request.
     *
     * @param e not used.
     */
    public void actionPerformed(final ActionEvent e)
    {
      attempExit();
    }
  }

  /**
   * Handles save requests in this editor.
   */
  private class SaveAction extends AbstractAction
  {
    /**
     * Defaultconstructor.
     */
    private SaveAction()
    {
      putValue(Action.NAME, getResources().getString("action.save.name")); //$NON-NLS-1$
      putValue(Action.SMALL_ICON, getResources().getIcon("action.save.small-icon")); //$NON-NLS-1$
    }

    /**
     * Handles the save request.
     *
     * @param e not used.
     */
    public void actionPerformed(final ActionEvent e)
    {
      save();
    }
  }

  /**
   * Handles import requests in this editor. Imports try to build a new description model from a given report
   * configuration.
   */
  private class ImportAction extends AbstractAction
  {
    /**
     * Defaultconstructor.
     */
    private ImportAction()
    {
      putValue(Action.NAME, getResources().getString("action.import.name")); //$NON-NLS-1$
      putValue(Action.SMALL_ICON, getResources().getIcon("action.import.small-icon")); //$NON-NLS-1$
      setEnabled(configurationToEdit != null);
    }

    /**
     * Handles the import request.
     *
     * @param e not used.
     */
    public void actionPerformed(final ActionEvent e)
    {
      if (configurationToEdit == null)
      {
        return;
      }

      final ConfigDescriptionModel model = getModel();
      model.importFromConfig(configurationToEdit);
      model.sort();
      setStatusText(getResources().getString("config-description-editor.import-complete")); //$NON-NLS-1$
    }
  }

  /**
   * Handles requests to add a new entry in this editor.
   */
  private class AddEntryAction extends AbstractAction
  {
    /**
     * Defaultconstructor.
     */
    private AddEntryAction()
    {
      putValue(Action.NAME, getResources().getString("action.add-entry.name")); //$NON-NLS-1$
      putValue(Action.SMALL_ICON, getResources().getIcon("action.add-entry.small-icon")); //$NON-NLS-1$
    }

    /**
     * Handles the add-entry request.
     *
     * @param e not used.
     */
    public void actionPerformed(final ActionEvent e)
    {
      final TextConfigDescriptionEntry te =
          new TextConfigDescriptionEntry
              (getResources().getString("config-description-editor.unnamed-entry")); //$NON-NLS-1$
      final ConfigDescriptionModel model = getModel();
      model.add(te);
      getEntryList().setSelectedIndex(model.getSize() - 1);
    }
  }

  /**
   * Handles requests to remove an entry from this editor.
   */
  private class RemoveEntryAction extends AbstractAction
  {
    /**
     * Defaultconstructor.
     */
    private RemoveEntryAction()
    {
      putValue(Action.NAME, getResources().getString("action.remove-entry.name")); //$NON-NLS-1$
      putValue(Action.SMALL_ICON, getResources().getIcon("action.remove-entry.small-icon")); //$NON-NLS-1$
    }

    /**
     * Handles the remove entry request.
     *
     * @param e not used.
     */
    public void actionPerformed(final ActionEvent e)
    {
      final int[] selectedEntries = getEntryList().getSelectedIndices();
      setSelectedEntry(null);
      final ConfigDescriptionModel model = getModel();
      model.removeAll(selectedEntries);
      getEntryList().clearSelection();
    }
  }

  /**
   * Handles load requests in this editor.
   */
  private class LoadAction extends AbstractAction
  {
    /**
     * Defaultconstructor.
     */
    private LoadAction()
    {
      putValue(Action.NAME, getResources().getString("action.load.name")); //$NON-NLS-1$
      putValue(Action.SMALL_ICON, getResources().getIcon("action.load.small-icon")); //$NON-NLS-1$
    }

    /**
     * Handles the laod request.
     *
     * @param e not used.
     */
    public void actionPerformed(final ActionEvent e)
    {
      load();
    }
  }

  /**
   * Handles update requests in the detail editor.
   */
  private class UpdateAction extends AbstractAction
  {
    /**
     * Defaultconstructor.
     */
    private UpdateAction()
    {
      putValue(Action.NAME, getResources().getString("action.update.name")); //$NON-NLS-1$
    }

    /**
     * Handles the update request.
     *
     * @param e not used.
     */
    public void actionPerformed(final ActionEvent e)
    {
      writeSelectedEntry();
    }
  }

  /**
   * Handles cancel requests in the detail editor.
   */
  private class CancelAction extends AbstractAction
  {
    /**
     * Defaultconstructor.
     */
    private CancelAction()
    {
      putValue(Action.NAME, getResources().getString("action.cancel.name")); //$NON-NLS-1$
    }

    /**
     * Handles the cancel request.
     *
     * @param e not used.
     */
    public void actionPerformed(final ActionEvent e)
    {
      final ConfigDescriptionEntry ce = getSelectedEntry();
      setSelectedEntry(null);
      setSelectedEntry(ce);
    }
  }

  /**
   * Handles editor type selections within the detail editor.
   */
  private class SelectTypeAction extends AbstractAction
  {
    /**
     * the selected type.
     */
    private final int type;

    /**
     * Creates a new select type action for the given name and type.
     *
     * @param name the name of the action.
     * @param type the type that should be selected whenever this action gets called.
     */
    private SelectTypeAction(final String name, final int type)
    {
      putValue(Action.NAME, name);
      this.type = type;
    }

    /**
     * Handles the select type request.
     *
     * @param e not used.
     */
    public void actionPerformed(final ActionEvent e)
    {
      setEntryType(type);
    }
  }

  /**
   * Handles the list selection in the list of available config keys.
   */
  private class ConfigListSelectionListener implements ListSelectionListener
  {
    private boolean inUpdate;

    /**
     * Defaultconstructor.
     */
    private ConfigListSelectionListener()
    {
    }

    /**
     * Called whenever the value of the selection changes.
     *
     * @param e the event that characterizes the change.
     */
    public void valueChanged(final ListSelectionEvent e)
    {
      if (inUpdate)
      {
        return;
      }

      inUpdate = true;
      try
      {
        final ConfigDescriptionEntry newEntry;
        final int selectedIndex = getEntryList().getSelectedIndex();
        if (selectedIndex == -1)
        {
          newEntry = null;
        }
        else
        {
          newEntry = getModel().get(selectedIndex);
        }

        final ConfigDescriptionEntry oldEntry = getSelectedEntry();
        if (oldEntry != null)
        {
          writeSelectedEntry();
        }

        if (newEntry != null)
        {
          final int index = getModel().indexOf(newEntry);
          if (getEntryList().getSelectedIndex() != index)
          {
            getEntryList().setSelectedIndex(index);
          }
          setSelectedEntry(newEntry);
        }
        else
        {
          getEntryList().setSelectedIndex(-1);
          setSelectedEntry(null);
        }
      }
      finally
      {
        inUpdate = false;
      }

    }
  }

  /**
   * Handles list selections in the enumeration detail editor.
   */
  private class EnumerationListSelectionHandler implements ListSelectionListener
  {
    /**
     * Defaultconstructor.
     */
    private EnumerationListSelectionHandler()
    {
    }

    /**
     * Called whenever the value of the selection changes.
     *
     * @param e the event that characterizes the change.
     */
    public void valueChanged(final ListSelectionEvent e)
    {
      if (getEnumEntryList().getSelectedIndex() == -1)
      {
        getEnumEntryEditField().setText(""); //$NON-NLS-1$
      }
      else
      {
        getEnumEntryEditField().setText((String) getEnumEntryListModel().get
            (getEnumEntryList().getSelectedIndex()));
      }
    }
  }

  /**
   * A ShortCut action to redefine the entries of the enumeration detail editor to represent a boolean value.
   */
  private class SetBooleanEnumEntryAction extends AbstractAction
  {
    /**
     * Defaultconstructor.
     */
    private SetBooleanEnumEntryAction()
    {
      putValue(Action.NAME, getResources().getString("action.boolean.name")); //$NON-NLS-1$
    }

    /**
     * Handles the boolean redefinition request.
     *
     * @param e not used.
     */
    public void actionPerformed(final ActionEvent e)
    {
      final DefaultListModel enumEntryListModel = getEnumEntryListModel();
      enumEntryListModel.clear();
      getEnumEntryEditField().setText(""); //$NON-NLS-1$
      enumEntryListModel.addElement("true"); //$NON-NLS-1$
      enumEntryListModel.addElement("false"); //$NON-NLS-1$
    }
  }

  /**
   * Handles the request to add a new enumeration entry to the detail editor.
   */
  private class AddEnumEntryAction extends AbstractAction
  {
    /**
     * Defaultconstructor.
     */
    private AddEnumEntryAction()
    {
      putValue(Action.NAME, getResources().getString("action.add-enum-entry.name")); //$NON-NLS-1$
    }

    /**
     * Handles the request to add a new enumeration entry to the detail editor.
     *
     * @param e not used.
     */
    public void actionPerformed(final ActionEvent e)
    {
      getEnumEntryListModel().addElement(getEnumEntryEditField().getText());
    }
  }

  /**
   * Handles the request to remove an enumeration entry to the detail editor.
   */
  private class RemoveEnumEntryAction extends AbstractAction
  {
    /**
     * Defaultconstructor.
     */
    private RemoveEnumEntryAction()
    {
      putValue(Action.NAME, getResources().getString("action.remove-enum-entry.name")); //$NON-NLS-1$
    }

    /**
     * Handles the request to remove an enumeration entry to the detail editor.
     *
     * @param e not used.
     */
    public void actionPerformed(final ActionEvent e)
    {
      final JList enumEntryList = getEnumEntryList();
      final DefaultListModel enumEntryListModel = getEnumEntryListModel();
      final int[] selectedEntries = enumEntryList.getSelectedIndices();
      for (int i = selectedEntries.length - 1; i >= 0; i--)
      {
        enumEntryListModel.remove(selectedEntries[i]);
      }
      enumEntryList.clearSelection();
    }
  }

  /**
   * Handles the request to update an enumeration entry to the detail editor.
   */
  private class UpdateEnumEntryAction extends AbstractAction
  {
    /**
     * Defaultconstructor.
     */
    private UpdateEnumEntryAction()
    {
      putValue(Action.NAME, getResources().getString("action.update-enum-entry.name")); //$NON-NLS-1$
    }

    /**
     * Handles the request to update an enumeration entry to the detail editor.
     *
     * @param e not used.
     */
    public void actionPerformed(final ActionEvent e)
    {
      final int idx = getEnumEntryList().getSelectedIndex();
      if (idx == -1)
      {
        getEnumEntryListModel().addElement(getEnumEntryEditField().getText());
      }
      else
      {
        getEnumEntryListModel().setElementAt(getEnumEntryEditField().getText(), idx);
      }
    }
  }

  /**
   * An internal value to mark a text detail editor type.
   */
  private static final int TYPE_TEXT = 0;
  /**
   * An internal value to mark a class detail editor type.
   */
  private static final int TYPE_CLASS = 1;
  /**
   * An internal value to mark a enumeration detail editor type.
   */
  private static final int TYPE_ENUM = 2;

  /**
   * A radio button to select the text editor type for the current key.
   */
  private JRadioButton rbText;
  /**
   * A radio button to select the class editor type for the current key.
   */
  private JRadioButton rbClass;
  /**
   * A radio button to select the enumeration editor type for the current key.
   */
  private JRadioButton rbEnum;
  /**
   * The list model used to collect and manage all available keys.
   */
  private ConfigDescriptionModel model;
  /**
   * The name of the currently edited key.
   */
  private JTextField keyNameField;
  /**
   * The description field contains a short description of the current key.
   */
  private JTextArea descriptionField;
  /**
   * Allows to check, whether the key is a global (boot-time) key.
   */
  private JCheckBox globalField;
  /**
   * Allows to check, whether the key is hidden.
   */
  private JCheckBox hiddenField;
  /**
   * The name of the base class for the class detail editor.
   */
  private JTextField baseClassField;
  /**
   * contains the currently selected entry of the enumeration detail editor.
   */
  private JTextField enumEntryEditField;
  /**
   * contains all entries of the enumeration detail editor.
   */
  private DefaultListModel enumEntryListModel;
  /**
   * The current resource bundle used to translate the strings in this dialog.
   */
  private ResourceBundleSupport resources;
  /**
   * This cardlayout is used to display the currently selected detail editor.
   */
  private CardLayout detailManager;
  /**
   * Contains the detail editor manager.
   */
  private JPanel detailManagerPanel;
  /**
   * Contains the detail editor for the key.
   */
  private JPanel detailEditorPane;
  /**
   * The list is used to manage all available keys.
   */
  private JList entryList;
  /**
   * This list is used to manage the available entries of the enumeration detail editor.
   */
  private JList enumEntryList;
  /**
   * the currently selected description entry.
   */
  private ConfigDescriptionEntry selectedEntry;
  /**
   * The file chooser is used to select the file for the load/save operations.
   */
  private JFileChooser fileChooser;
  /**
   * Serves as statusline for the dialog.
   */
  private JLabel statusHolder;
  /**
   * The currently selected detail editor type.
   */
  private int type;

  private Configuration configurationToEdit;


  public ConfigDescriptionEditor()
  {
    this(ConfigEditorBoot.class.getName());
  }
  /**
   * Constructs a ConfigDescriptionEditor that is initially invisible.
   */
  public ConfigDescriptionEditor(final AbstractBoot boot)
  {
    if (boot != null)
    {
      boot.start();
      this.configurationToEdit = boot.getGlobalConfig();
    }

    init();
  }


  /**
   * Constructs a ConfigDescriptionEditor that is initially invisible.
   */
  public ConfigDescriptionEditor(final String booterClass)
  {
    final AbstractBoot boot = (AbstractBoot)
        ObjectUtilities.loadAndInstantiate(booterClass, ConfigDescriptionEditor.class, AbstractBoot.class);
    if (boot != null)
    {
      boot.start();
      this.configurationToEdit = boot.getGlobalConfig();
    }

    init();
  }

  private void init()
  {
    this.resources = Messages.getInstance();

    setTitle(resources.getString("config-description-editor.title")); //$NON-NLS-1$
    final JPanel contentPane = new JPanel();
    contentPane.setLayout(new BorderLayout());

    detailEditorPane = createEditPane();
    final JSplitPane splitPane = new JSplitPane
        (JSplitPane.HORIZONTAL_SPLIT, createEntryList(), detailEditorPane);

    contentPane.add(splitPane, BorderLayout.CENTER);
    contentPane.add(createButtonPane(), BorderLayout.SOUTH);

    final JPanel cPaneStatus = new JPanel();
    cPaneStatus.setLayout(new BorderLayout());
    cPaneStatus.add(contentPane, BorderLayout.CENTER);
    cPaneStatus.add(createStatusBar(), BorderLayout.SOUTH);

    setContentPane(cPaneStatus);
    setEntryType(ConfigDescriptionEditor.TYPE_TEXT);
    setSelectedEntry(null);

    fileChooser = new JFileChooser();
    fileChooser.addChoosableFileFilter(new FilesystemFilter
        (".xml", resources.getString("config-description-editor.xml-files"))); //$NON-NLS-1$ //$NON-NLS-2$
    fileChooser.setMultiSelectionEnabled(false);

    setStatusText(resources.getString("config-description-editor.welcome")); //$NON-NLS-1$

    addWindowListener(new CloseHandler());
  }

  /**
   * Creates and returns the entry list component that will hold all config description entries within a list.
   *
   * @return the created entry list.
   */
  private JPanel createEntryList()
  {
    final Action addEntryAction = new AddEntryAction();
    final Action removeEntryAction = new RemoveEntryAction();

    model = new ConfigDescriptionModel();
    entryList = new JList(model);
    entryList.addListSelectionListener(new ConfigListSelectionListener());

    final JToolBar toolbar = new JToolBar();
    toolbar.setFloatable(false);
    toolbar.add(addEntryAction);
    toolbar.add(removeEntryAction);

    final JPanel panel = new JPanel();
    panel.setMinimumSize(new Dimension(200, 0));
    panel.setLayout(new BorderLayout());
    panel.add(toolbar, BorderLayout.NORTH);
    panel.add(new JScrollPane
        (entryList, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
            ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER);
    return panel;
  }

  /**
   * Returns the JList component containing all entries of the enumeration detail editor.
   *
   * @return the enumeration entry list.
   */
  protected JList getEnumEntryList()
  {
    return enumEntryList;
  }

  /**
   * Returns the text field containing the currently edited enumeration entry.
   *
   * @return the textfield containing the current entry.
   */
  protected JTextField getEnumEntryEditField()
  {
    return enumEntryEditField;
  }

  /**
   * Returns the List Model containing all entries of the current enumeration entry editor.
   *
   * @return the entry list.
   */
  protected DefaultListModel getEnumEntryListModel()
  {
    return enumEntryListModel;
  }

  /**
   * Returns the JList component containing all configuration entries.
   *
   * @return the entry list.
   */
  protected JList getEntryList()
  {
    return entryList;
  }

  /**
   * Creates a panel containing all dialog control buttons, like close, load, save and import.
   *
   * @return the button panel.
   */
  private JPanel createButtonPane()
  {
    final Action closeAction = new CloseAction();
    final Action saveAction = new SaveAction();
    final Action loadAction = new LoadAction();
    final Action importAction = new ImportAction();

    final JPanel panel = new JPanel();
    panel.setLayout(new FlowLayout(FlowLayout.RIGHT));
    panel.setBorder(new EmptyBorder(5, 5, 5, 5));

    final JPanel buttonHolder = new JPanel();
    buttonHolder.setLayout(new GridLayout(1, 4, 5, 5));
    buttonHolder.add(new JButton(importAction));
    buttonHolder.add(new JButton(loadAction));
    buttonHolder.add(new JButton(saveAction));
    buttonHolder.add(new JButton(closeAction));

    panel.add(buttonHolder);
    return panel;
  }

  /**
   * Creates the detail editor panel. This panel will contain all specific editors for the keys.
   *
   * @return the detail editor panel.
   */
  private JPanel createEditPane()
  {

    final JPanel buttonHolder = new JPanel();
    buttonHolder.setLayout(new GridLayout(1, 4, 5, 5));
    buttonHolder.add(new JButton(new CancelAction()));
    buttonHolder.add(new JButton(new UpdateAction()));

    final JPanel buttonPanel = new JPanel();
    buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
    buttonPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
    buttonPanel.add(buttonHolder);

    final JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout());
    panel.add(createDetailEditorPanel(), BorderLayout.CENTER);
    panel.add(buttonPanel, BorderLayout.SOUTH);
    return panel;
  }

  /**
   * Creates the enumeration detail editor.
   *
   * @return the enumeration detail editor.
   */
  private JPanel createEnumerationEditor()
  {
    enumEntryEditField = new JTextField();
    enumEntryListModel = new DefaultListModel();

    enumEntryList = new JList(enumEntryListModel);
    enumEntryList.addListSelectionListener(new EnumerationListSelectionHandler());

    final JPanel listPanel = new JPanel();
    listPanel.setLayout(new BorderLayout());
    listPanel.add(enumEntryEditField, BorderLayout.NORTH);
    listPanel.add(new JScrollPane(enumEntryList), BorderLayout.CENTER);

    final JPanel buttonPanel = new JPanel();
    buttonPanel.setLayout(new GridLayout(5, 1));
    buttonPanel.add(new JButton(new AddEnumEntryAction()));
    buttonPanel.add(new JButton(new RemoveEnumEntryAction()));
    buttonPanel.add(new JButton(new UpdateEnumEntryAction()));
    buttonPanel.add(new JPanel());
    buttonPanel.add(new JButton(new SetBooleanEnumEntryAction()));

    final JPanel buttonCarrier = new JPanel();
    buttonCarrier.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
    buttonCarrier.add(buttonPanel);

    final JPanel editorPanel = new JPanel();
    editorPanel.setLayout(new BorderLayout());
    editorPanel.add(listPanel, BorderLayout.CENTER);
    editorPanel.add(buttonCarrier, BorderLayout.EAST);
    return editorPanel;
  }

  /**
   * Creates the class detail editor.
   *
   * @return the class detail editor.
   */
  private JPanel createClassEditor()
  {
    baseClassField = new JTextField();
    final JLabel baseClassValidateMessage = new JLabel(" ");

    final JLabel textLabel = new JLabel
        (resources.getString("config-description-editor.baseclass")); //$NON-NLS-1$
    final JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout());
    panel.add(textLabel, BorderLayout.WEST);
    panel.add(baseClassField, BorderLayout.CENTER);
    panel.add(baseClassValidateMessage, BorderLayout.SOUTH);

    final JPanel carrier = new JPanel();
    carrier.setLayout(new BorderLayout());
    carrier.add(panel, BorderLayout.NORTH);
    return carrier;
  }

  /**
   * Creates the text detail editor.
   *
   * @return the text detail editor.
   */
  private JPanel createTextEditor()
  {
    final JLabel textLabel = new JLabel
        (resources.getString("config-description-editor.text-editor-message")); //$NON-NLS-1$
    final JPanel panel = new JPanel();
    panel.setLayout(new FlowLayout());
    panel.add(textLabel);
    return panel;
  }

  /**
   * Creates the common entry detail editor. This editor contains all shared properties.
   *
   * @return the common entry editor.
   */
  private JPanel createDetailEditorPanel()
  {
    final JLabel keyNameLabel = new JLabel
        (resources.getString("config-description-editor.keyname")); //$NON-NLS-1$
    final JLabel descriptionLabel = new JLabel
        (resources.getString("config-description-editor.description")); //$NON-NLS-1$
    final JLabel typeLabel = new JLabel(resources.getString("config-description-editor.type")); //$NON-NLS-1$
    final JLabel globalLabel = new JLabel(resources.getString("config-description-editor.global")); //$NON-NLS-1$
    final JLabel hiddenLabel = new JLabel(resources.getString("config-description-editor.hidden")); //$NON-NLS-1$

    hiddenField = new JCheckBox();
    globalField = new JCheckBox();
    final String font = ConfigEditorBoot.getInstance().getGlobalConfig().getConfigProperty
        (ConfigDescriptionEditor.EDITOR_FONT_KEY, "Monospaced"); //$NON-NLS-1$
    final int fontSize = ParserUtil.parseInt
        (ConfigEditorBoot.getInstance().getGlobalConfig().getConfigProperty
            (ConfigDescriptionEditor.EDITOR_FONT_SIZE_KEY), 12);
    descriptionField = new JTextArea();
    descriptionField.setFont(new Font(font, Font.PLAIN, fontSize));
    descriptionField.setLineWrap(true);
    descriptionField.setWrapStyleWord(true);
    keyNameField = new JTextField();

    final JPanel enumerationEditor = createEnumerationEditor();
    final JPanel textEditor = createTextEditor();
    final JPanel classEditor = createClassEditor();

    detailManagerPanel = new JPanel();
    detailManager = new CardLayout();
    detailManagerPanel.setLayout(detailManager);
    detailManagerPanel.add(classEditor, ConfigDescriptionEditor.CLASS_DETAIL_EDITOR_NAME);
    detailManagerPanel.add(textEditor, ConfigDescriptionEditor.TEXT_DETAIL_EDITOR_NAME);
    detailManagerPanel.add(enumerationEditor, ConfigDescriptionEditor.ENUM_DETAIL_EDITOR_NAME);

    final JPanel commonEntryEditorPanel = new JPanel();
    commonEntryEditorPanel.setLayout(new GridBagLayout());
    commonEntryEditorPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));

    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.insets = new Insets(3, 1, 1, 1);
    commonEntryEditorPanel.add(keyNameLabel, gbc);

    gbc = new GridBagConstraints();
    gbc.gridx = 1;
    gbc.gridy = 0;
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.weightx = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.insets = new Insets(3, 1, 1, 1);
    gbc.ipadx = 120;
    commonEntryEditorPanel.add(keyNameField, gbc);

    gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.gridy = 1;
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.insets = new Insets(3, 1, 1, 1);
    commonEntryEditorPanel.add(descriptionLabel, gbc);

    gbc = new GridBagConstraints();
    gbc.gridx = 1;
    gbc.gridy = 1;
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.weightx = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.insets = new Insets(3, 1, 1, 1);
    gbc.ipadx = 120;
    gbc.ipady = 120;
    commonEntryEditorPanel.add(new JScrollPane
        (descriptionField,
            ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
            ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER), gbc);

    gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.gridy = 2;
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.insets = new Insets(3, 1, 1, 1);
    commonEntryEditorPanel.add(globalLabel, gbc);

    gbc = new GridBagConstraints();
    gbc.gridx = 1;
    gbc.gridy = 2;
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.weightx = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.insets = new Insets(3, 1, 1, 1);
    gbc.ipadx = 120;
    commonEntryEditorPanel.add(globalField, gbc);

    gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.gridy = 3;
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.insets = new Insets(3, 1, 1, 1);
    commonEntryEditorPanel.add(hiddenLabel, gbc);

    gbc = new GridBagConstraints();
    gbc.gridx = 1;
    gbc.gridy = 3;
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.weightx = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.insets = new Insets(3, 1, 1, 1);
    gbc.ipadx = 120;
    commonEntryEditorPanel.add(hiddenField, gbc);

    gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.gridy = 4;
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.insets = new Insets(3, 1, 1, 1);
    commonEntryEditorPanel.add(typeLabel, gbc);

    gbc = new GridBagConstraints();
    gbc.gridx = 1;
    gbc.gridy = 4;
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.weightx = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.insets = new Insets(3, 1, 1, 1);
    gbc.ipadx = 120;
    commonEntryEditorPanel.add(createTypeSelectionPane(), gbc);

    gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.gridy = 5;
    gbc.gridwidth = 2;
    gbc.weighty = 1;
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.weightx = 1;
    gbc.fill = GridBagConstraints.BOTH;
    gbc.insets = new Insets(3, 1, 1, 1);
    gbc.ipadx = 120;
    commonEntryEditorPanel.add(detailManagerPanel, gbc);

    return commonEntryEditorPanel;
  }

  /**
   * Creates the type selection panel containing some radio buttons to define the detail editor type.
   *
   * @return the type selection panel.
   */
  private JPanel createTypeSelectionPane()
  {
    final JPanel panel = new JPanel();
    panel.setLayout(new GridLayout(3, 1));

    rbText = new JRadioButton(new SelectTypeAction
        (resources.getString("config-description-editor.type-text"), ConfigDescriptionEditor.TYPE_TEXT)); //$NON-NLS-1$
    rbClass = new JRadioButton(new SelectTypeAction
        (resources.getString("config-description-editor.type-class"),
            ConfigDescriptionEditor.TYPE_CLASS)); //$NON-NLS-1$
    rbEnum = new JRadioButton(new SelectTypeAction
        (resources.getString("config-description-editor.type-enum"), ConfigDescriptionEditor.TYPE_ENUM)); //$NON-NLS-1$

    final ButtonGroup bg = new ButtonGroup();
    bg.add(rbText);
    bg.add(rbClass);
    bg.add(rbEnum);

    panel.add(rbText);
    panel.add(rbClass);
    panel.add(rbEnum);

    return panel;
  }

  /**
   * Creates the statusbar for this frame. Use setStatus() to display text on the status bar.
   *
   * @return the status bar.
   */
  protected JPanel createStatusBar()
  {
    final JPanel statusPane = new JPanel();
    statusPane.setLayout(new BorderLayout());
    statusPane.setBorder(BorderFactory.createLineBorder(UIManager.getDefaults().getColor(
        "controlShadow"))); //$NON-NLS-1$
    statusHolder = new JLabel(" "); //$NON-NLS-1$
    statusPane.setMinimumSize(statusHolder.getPreferredSize());
    statusPane.add(statusHolder, BorderLayout.WEST);

    return statusPane;
  }

  /**
   * Defines the status text for this dialog.
   *
   * @param text the new status text.
   */
  protected void setStatusText(final String text)
  {
    statusHolder.setText(text);
  }

  /**
   * Returns the currently visible status text of this dialog.
   *
   * @return the status text.
   */
  protected String getStatusText()
  {
    return statusHolder.getText();
  }

  /**
   * Sets the entry type for the current config description entry. This also selects and activates the correct detail
   * editor for this type.
   *
   * @param type the type of the currently selected entry.
   */
  protected void setEntryType(final int type)
  {
    this.type = type;
    if (type == ConfigDescriptionEditor.TYPE_CLASS)
    {
      detailManager.show(detailManagerPanel, ConfigDescriptionEditor.CLASS_DETAIL_EDITOR_NAME);
      rbClass.setSelected(true);
    }
    else if (type == ConfigDescriptionEditor.TYPE_ENUM)
    {
      detailManager.show(detailManagerPanel, ConfigDescriptionEditor.ENUM_DETAIL_EDITOR_NAME);
      rbEnum.setSelected(true);
    }
    else
    {
      detailManager.show(detailManagerPanel, ConfigDescriptionEditor.TEXT_DETAIL_EDITOR_NAME);
      rbText.setSelected(true);
    }
    invalidate();
  }

  /**
   * Returns the current entry type.
   *
   * @return the current entry type.
   */
  protected int getEntryType()
  {
    return type;
  }

  /**
   * Returns the currently select entry from the entry list model.
   *
   * @return the currently selected entry.
   */
  protected ConfigDescriptionEntry getSelectedEntry()
  {
    return selectedEntry;
  }

  /**
   * Defines the currently selected entry from the entry list model and updates the detail editor to reflect the data
   * from the entry.
   *
   * @param selectedEntry the selected entry.
   */
  protected void setSelectedEntry(final ConfigDescriptionEntry selectedEntry)
  {
    this.selectedEntry = selectedEntry;

    enumEntryEditField.setText(""); //$NON-NLS-1$
    enumEntryListModel.clear();
    baseClassField.setText(""); //$NON-NLS-1$

    if (this.selectedEntry == null)
    {
      deepEnable(detailEditorPane, false);
    }
    else
    {
      deepEnable(detailEditorPane, true);
      keyNameField.setText(selectedEntry.getKeyName());
      globalField.setSelected(selectedEntry.isGlobal());
      hiddenField.setSelected(selectedEntry.isHidden());
      descriptionField.setText(selectedEntry.getDescription());
      if (selectedEntry instanceof ClassConfigDescriptionEntry)
      {
        final ClassConfigDescriptionEntry ce = (ClassConfigDescriptionEntry) selectedEntry;
        setEntryType(ConfigDescriptionEditor.TYPE_CLASS);
        if (ce.getBaseClass() != null)
        {
          baseClassField.setText(ce.getBaseClass().getName());
        }
      }
      else if (selectedEntry instanceof EnumConfigDescriptionEntry)
      {
        final EnumConfigDescriptionEntry en = (EnumConfigDescriptionEntry) selectedEntry;
        final String[] enums = en.getOptions();
        for (int i = 0; i < enums.length; i++)
        {
          enumEntryListModel.addElement(enums[i]);
        }
        setEntryType(ConfigDescriptionEditor.TYPE_ENUM);
      }
      else
      {
        setEntryType(ConfigDescriptionEditor.TYPE_TEXT);
      }
    }
  }

  /**
   * A utility method to enable or disable a component and all childs.
   *
   * @param comp  the component that should be enabled or disabled.
   * @param state the new enable state.
   */
  private void deepEnable(final Component comp, final boolean state)
  {
    comp.setEnabled(state);
    if (comp instanceof Container)
    {
      final Container cont = (Container) comp;
      final Component[] childs = cont.getComponents();
      for (int i = 0; i < childs.length; i++)
      {
        deepEnable(childs[i], state);
      }
    }
  }

  /**
   * Saves the config description model in a xml file.
   */
  protected void save()
  {
    fileChooser.setVisible(true);

    final int option = fileChooser.showSaveDialog(this);
    if (option == JFileChooser.APPROVE_OPTION)
    {
      OutputStream out = null;
      try
      {
        out = new BufferedOutputStream(new FileOutputStream(fileChooser.getSelectedFile()));
        model.save(out, "ISO-8859-1"); //$NON-NLS-1$
        out.close();
        setStatusText(resources.getString("config-description-editor.save-complete")); //$NON-NLS-1$
      }
      catch (Exception ioe)
      {
        ConfigDescriptionEditor.logger.debug("Failed", ioe); //$NON-NLS-1$
        final String message = MessageFormat.format
            (resources.getString("config-description-editor.save-failed"), //$NON-NLS-1$
                new Object[]{ioe.getMessage()});
        setStatusText(message);
      }
      finally
      {
        if (out != null)
        {
          try
          {
            out.close();
          }
          catch (IOException e)
          {
            // ignored .. at least we tried it ..
          }
        }
      }
    }
  }

  /**
   * Loads the config description model from a xml file.
   */
  protected void load()
  {
    fileChooser.setVisible(true);

    final int option = fileChooser.showOpenDialog(this);
    if (option == JFileChooser.APPROVE_OPTION)
    {
      InputStream in = null;
      try
      {
        final FileInputStream fileIn = new FileInputStream(fileChooser.getSelectedFile());
        in = new BufferedInputStream(fileIn);
        model.load(in);
        model.sort();
        setStatusText(resources.getString("config-description-editor.load-complete")); //$NON-NLS-1$
      }
      catch (Exception ioe)
      {
        ConfigDescriptionEditor.logger.debug("Load Failed", ioe); //$NON-NLS-1$
        final String message = MessageFormat.format
            (resources.getString("config-description-editor.load-failed"), //$NON-NLS-1$
                new Object[]{ioe.getMessage()});
        setStatusText(message);
      }
      finally
      {
        if (in != null)
        {
          try
          {
            in.close();
          }
          catch (IOException e)
          {
            // ignored .. at least we tried it ..
          }
        }
      }
    }
  }

  /**
   * Updates the currently selected entry from the values found in the detail editor.
   */
  protected void writeSelectedEntry()
  {
    final ConfigDescriptionEntry entry;
    switch (getEntryType())
    {
      case ConfigDescriptionEditor.TYPE_CLASS:
      {
        final ClassConfigDescriptionEntry ce = new ClassConfigDescriptionEntry(keyNameField.getText());
        ce.setDescription(descriptionField.getText());
        ce.setGlobal(globalField.isSelected());
        ce.setHidden(hiddenField.isSelected());
        try
        {
          final String className = baseClassField.getText();
          if (className == null)
          {
            ce.setBaseClass(Object.class);
          }
          else
          {
            final ClassLoader classLoader = ObjectUtilities.getClassLoader(getClass());
            final Class c = Class.forName(className, false, classLoader);
            ce.setBaseClass(c);
          }
        }
        catch (Exception e)
        {
          // invalid
          ConfigDescriptionEditor.logger.debug("Class is invalid; defaulting to Object.class"); //$NON-NLS-1$
          ce.setBaseClass(Object.class);
        }
        entry = ce;
        break;
      }
      case ConfigDescriptionEditor.TYPE_ENUM:
      {
        final EnumConfigDescriptionEntry ece = new EnumConfigDescriptionEntry(keyNameField.getText());
        ece.setDescription(descriptionField.getText());
        ece.setGlobal(globalField.isSelected());
        ece.setHidden(hiddenField.isSelected());
        final String[] enumEntries = new String[enumEntryListModel.getSize()];
        for (int i = 0; i < enumEntryListModel.getSize(); i++)
        {
          enumEntries[i] = String.valueOf(enumEntryListModel.get(i));
        }
        ece.setOptions(enumEntries);
        entry = ece;
        break;
      }
      default:
      {
        final TextConfigDescriptionEntry te = new TextConfigDescriptionEntry(keyNameField.getText());
        te.setDescription(descriptionField.getText());
        te.setGlobal(globalField.isSelected());
        te.setHidden(hiddenField.isSelected());
        entry = te;
        break;
      }
    }

    final ConfigDescriptionEntry selectedEntry = getSelectedEntry();
    if (selectedEntry == null)
    {
      model.add(entry);
      return;
    }

    if (ObjectUtilities.equal(selectedEntry.getKeyName(), entry.getKeyName()) == false)
    {
      model.remove(selectedEntry);
    }

    model.add(entry);
  }

  /**
   * Returns the config description model containing all metainformation about the configuration.
   *
   * @return the config description model.
   */
  protected ConfigDescriptionModel getModel()
  {
    return model;
  }

  /**
   * Handles the attemp to quit the program. This method shuts down the VM.
   */
  protected void attempExit()
  {
    System.exit(0);
  }

  /**
   * Returns the resource bundle of this editor for translating strings.
   *
   * @return the resource bundle.
   */
  protected ResourceBundleSupport getResources()
  {
    return resources;
  }

  /**
   * The main entry point to start the detail editor.
   *
   * @param args ignored.
   */
  public static void main(final String[] args)
  {
    ConfigEditorBoot.getInstance().start();

    if (args.length == 0)
    {
      final ConfigDescriptionEditor ed = new ConfigDescriptionEditor();
      ed.pack();
      ed.setVisible(true);
    }
    else
    {
      final AbstractBoot boot = AbstractBoot.loadBooter(args[0], ConfigDescriptionEditor.class);
      if (boot == null)
      {
        System.out.println("Error: Unable to load the specified booter class: " + args[0]);
        System.exit(-1);
      }
      final ConfigDescriptionEditor ed = new ConfigDescriptionEditor(boot);
      ed.pack();
      ed.setVisible(true);
    }
  }
}
TOP

Related Classes of org.pentaho.reporting.tools.configeditor.ConfigDescriptionEditor$CancelAction

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.