Package org.pentaho.reporting.designer.core.util.table

Source Code of org.pentaho.reporting.designer.core.util.table.ResourcePropertyEditorComponent

/*!
* 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) 2002-2013 Pentaho Corporation..  All rights reserved.
*/

package org.pentaho.reporting.designer.core.util.table;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.filechooser.FileFilter;

import org.pentaho.reporting.designer.core.Messages;
import org.pentaho.reporting.designer.core.editor.ReportDocumentContext;
import org.pentaho.reporting.designer.core.util.UtilMessages;
import org.pentaho.reporting.engine.classic.core.designtime.DesignTimeUtil;
import org.pentaho.reporting.engine.classic.core.modules.parser.base.ClassicEngineFactoryParameters;
import org.pentaho.reporting.libraries.base.util.FilesystemFilter;
import org.pentaho.reporting.libraries.base.util.IOUtils;
import org.pentaho.reporting.libraries.base.util.ObjectUtilities;
import org.pentaho.reporting.libraries.base.util.StringUtils;
import org.pentaho.reporting.libraries.designtime.swing.event.DocumentChangeHandler;
import org.pentaho.reporting.libraries.designtime.swing.filechooser.CommonFileChooser;
import org.pentaho.reporting.libraries.designtime.swing.filechooser.FileChooserService;
import org.pentaho.reporting.libraries.designtime.swing.propertyeditors.ValidatingPropertyEditorComponent;
import org.pentaho.reporting.libraries.repository.DefaultMimeRegistry;
import org.pentaho.reporting.libraries.resourceloader.LoaderParameterKey;
import org.pentaho.reporting.libraries.resourceloader.ResourceKey;
import org.pentaho.reporting.libraries.resourceloader.ResourceKeyCreationException;
import org.pentaho.reporting.libraries.resourceloader.ResourceKeyUtils;
import org.pentaho.reporting.libraries.resourceloader.ResourceLoadingException;

/**
* A UI component which will capture a resource name / location and if that
* resource should be linked externally or embedded in the report.
*
* @author Thomas Morgner
* @author David Kincade
* @author Ezequiel Cuellar
*/
public class ResourcePropertyEditorComponent extends JComponent implements ValidatingPropertyEditorComponent
{
  /**
   * Enumeration defining the possible values for Document Locations
   */
  public enum DocumentLocation
  {
    LINK, EMBED
  }

  private static final DefaultMimeRegistry mimeRegistry = new DefaultMimeRegistry();

  private JRadioButton linkToRadio;
  private JRadioButton embedRadio;
  private JTextField sourceTextField;
  private ReportDocumentContext reportRenderContext;
  private Object currentValue;
  private String lastTextValue;
  private DocumentLocation lastDocumentLocation;
  private boolean disableEvents;

  /**
   * Constructor which sets up the location of all the elements on this component
   *
   * @param reportRenderContext the report render context for the current report
   */
  public ResourcePropertyEditorComponent(final ReportDocumentContext reportRenderContext)
  {
    // Get the information used to embed items in the document bundle
    if (reportRenderContext == null)
    {
      throw new NullPointerException("The ReportRenderContext must not be null");
    }
    this.reportRenderContext = reportRenderContext;

    final SourceChangeHandler changeHandler = new SourceChangeHandler();
    sourceTextField = new JTextField(35);
    sourceTextField.getDocument().addDocumentListener(changeHandler);

    linkToRadio = new JRadioButton(UtilMessages.getInstance().getString("ResourcePropertyEditorComponent.LinkTo"));
    linkToRadio.setSelected(true);
    linkToRadio.addChangeListener(changeHandler);

    embedRadio = new JRadioButton(UtilMessages.getInstance().getString("ResourcePropertyEditorComponent.Embed"));
    embedRadio.addChangeListener(changeHandler);

    final JPanel identifierSelectorPanel = new JPanel(new BorderLayout());
    identifierSelectorPanel.add(sourceTextField, BorderLayout.CENTER);
    identifierSelectorPanel.add(new JButton(new FileSelectAction()), BorderLayout.EAST);

    final ButtonGroup buttonGroup = new ButtonGroup();
    buttonGroup.add(linkToRadio);
    buttonGroup.add(embedRadio);

    final JPanel identifierPane = new JPanel(new BorderLayout());
    identifierPane.setBorder(BorderFactory.createEmptyBorder(0, 6, 0, 0));
    identifierPane.add(new JLabel(UtilMessages.getInstance().getString("ResourcePropertyEditorComponent.SourceLabel")), BorderLayout.NORTH);
    identifierPane.add(identifierSelectorPanel, BorderLayout.CENTER);

    final JPanel selectionPanel = new JPanel(new GridLayout(2, 1));
    selectionPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
    selectionPanel.add(linkToRadio);
    selectionPanel.add(embedRadio);

    setLayout(new BorderLayout());
    add(identifierPane, BorderLayout.CENTER);
    add(selectionPanel, BorderLayout.SOUTH);
  }

  /**
   * Returns the current value of the property as a <code>ResourceKey</code>.
   * <br/>
   * If the key is embedded, additional information will be stored in the <code>Factory Parameters</code>
   * in the following way:
   * <table>
   * <row><th>key</th><th>value</th></row>
   * <row><td>original_value</td><td>The string version of the key that was original entered</td></row>
   * <row><td>embedded</td><td>Indicates if the resource should be / is embedded in the document bundle</td></row>
   * </table>
   *
   * @return the ResourceKey being created in this
   */
  public Object getValue()
  {
    // If nothing has changed since the last check, we should return the current value
    // instead of recomputing it
    final String currentTextValue = sourceTextField.getText();
    final DocumentLocation currentDocumentLocation = getDocumentLocation();
    if (currentTextValue.equals(lastTextValue) &&
        currentDocumentLocation.equals(lastDocumentLocation))
    {
      return currentValue;
    }

    if (StringUtils.isEmpty(currentTextValue))
    {
      lastTextValue = currentTextValue;
      lastDocumentLocation = currentDocumentLocation;
      return null;
    }
    // Try to compute a ResourceKey from the current data
    try
    {
      currentValue = createResourceKey(currentTextValue, currentDocumentLocation);
    }
    catch (Exception ignored)
    {
      // The text does not yield a valid ResourceKey
      currentValue = currentTextValue;
    }

    lastTextValue = currentTextValue;
    lastDocumentLocation = currentDocumentLocation;
    return currentValue;
  }

  /**
   * Creates a ResourceKey based on the current values in this component.
   *
   * @param source the current location used in the creation of the resource key
   * @param docLoc the link/embed flag used in the creation of the resource key
   * @return the newly created ResourceKey
   * @throws ResourceKeyCreationException indicates the current values do not generate a valid ResourceKey
   */
  private Object createResourceKey(final String source,
                                   final DocumentLocation docLoc)
      throws ResourceKeyCreationException, IOException, ResourceLoadingException
  {
    if (StringUtils.isEmpty(source, true))
    {
      return null;
    }

    // If we are embedding the key, create some factory patameters
    if (DocumentLocation.EMBED.equals(docLoc))
    {
      final String mimeType = mimeRegistry.getMimeType(source);
      final String pattern = "resources/image{0}" + IOUtils.getInstance().getFileExtension(source); // NON-NLS
      final Map<LoaderParameterKey, String> parameters = new HashMap<LoaderParameterKey, String>();
      parameters.put(ClassicEngineFactoryParameters.ORIGINAL_VALUE, source);
      parameters.put(ClassicEngineFactoryParameters.MIME_TYPE, mimeType);
      parameters.put(ClassicEngineFactoryParameters.PATTERN, pattern);
      parameters.put(ClassicEngineFactoryParameters.EMBED, "true"); // NON-NLS
      // create an embedded key in here.
      final ResourceKey key = ResourceKeyUtils.toResourceKey
          (source, reportRenderContext.getResourceManager(),
              reportRenderContext.getReportDefinition().getContentBase(), parameters);
      return ResourceKeyUtils.embedResourceInKey(reportRenderContext.getResourceManager(),
          key, key.getFactoryParameters());
    }

    // See if we can create a valid resource key
    final ResourceKey contentBaseKey = reportRenderContext.getReportDefinition().getContentBase();
    final ResourceKey resourceKey = ResourceKeyUtils.toResourceKey
        (source, reportRenderContext.getResourceManager(), contentBaseKey, Collections.EMPTY_MAP);
    if (isDerivedKey(resourceKey, contentBaseKey))
    {
      return source;
    }
    return resourceKey;
  }

  private boolean isDerivedKey(final ResourceKey key, final ResourceKey contentKey)
  {
    if (contentKey == null)
    {
      return false;
    }
    if (contentKey.getSchema().equals(key.getSchema()))
    {
      return true;
    }
    return isDerivedKey(key, contentKey.getParent());
  }

  /**
   * Sets the value of the source field
   *
   * @param value the current string value
   */
  public void setValue(final String value)
  {
    sourceTextField.setText(value);
    setDocumentLocation(DocumentLocation.LINK);
    fireValueChangeEvent();
  }


  /**
   * Sets the value of the source field
   *
   * @param object the current value
   */
  public void setValue(final Object object)
  {
    // Nothing to do if nothing is changing
    if (ObjectUtilities.equal(currentValue, object))
    {
      return;
    }

    try
    {
      disableEvents = true;
      // Set the internal fields properly
      if (object == null)
      {
        sourceTextField.setText("");
        setDocumentLocation(DocumentLocation.LINK);
      }
      else if (object instanceof ResourceKey)
      {
        // Is the resource key an embedded resource key?
        final ResourceKey resourceKey = (ResourceKey) object;
        final Object originalValue =
            resourceKey.getFactoryParameters().get(ClassicEngineFactoryParameters.ORIGINAL_VALUE);
        if (originalValue != null)
        {
          sourceTextField.setText(String.valueOf(originalValue));
          setDocumentLocation(DocumentLocation.EMBED);
        }
        else
        {
          sourceTextField.setText(resourceKey.getIdentifierAsString());
          setDocumentLocation(DocumentLocation.LINK);
        }
      }
      else
      {
        sourceTextField.setText(String.valueOf(object));
        setDocumentLocation(DocumentLocation.LINK);
      }

      // Save the current values as the latest values
      currentValue = object;
    }
    finally
    {
      disableEvents = false;
    }
    // Let everyone know there has been a change in values
    fireValueChangeEvent();
  }

  /**
   * Returns the current value of the <code>embed / link</code> radio button
   *
   * @return the current value of the document location
   */
  private DocumentLocation getDocumentLocation()
  {
    return (linkToRadio.isSelected() ? DocumentLocation.LINK : DocumentLocation.EMBED);
  }

  /**
   * Sets the document location to the specified value
   *
   * @param documentLocation the value of the document location
   */
  private void setDocumentLocation(final DocumentLocation documentLocation)
  {
    if (DocumentLocation.LINK.equals(documentLocation))
    {
      linkToRadio.setSelected(true);
      embedRadio.setSelected(false);
    }
    else
    {
      linkToRadio.setSelected(false);
      embedRadio.setSelected(true);
    }
  }

  /**
   * Indicates if the current value is a valid value. The current value is valid if
   * the document location is LINK, or the current value is a ResourceKey and the document
   * location is embed.
   */
  public boolean isValidEditorValue()
  {
    if (getDocumentLocation().equals(DocumentLocation.LINK))
    {
      return true;
    }

    final Object o = getValue();
    return o instanceof ResourceKey;
  }

  /**
   * Notifies all the listeners that a value on this component has changed
   */
  private void fireValueChangeEvent()
  {
    if (disableEvents)
    {
      return;
    }

    final Object oldValue = currentValue;
    final Object newValue = getValue();
    firePropertyChange(null, oldValue, newValue);
  }

  /**
   * Notifies all the listeners that a value on this component has changed
   */
  private void fireRadioChangeEvent()
  {
    if (disableEvents)
    {
      return;
    }

    final Object oldValue = lastDocumentLocation;
    final Object newValue = getDocumentLocation();
    firePropertyChange(null, oldValue, newValue);
  }


  /**
   * The class which will handle the notification changes when the source text field changes.
   */
  private class SourceChangeHandler extends DocumentChangeHandler implements ChangeListener
  {
    private SourceChangeHandler()
    {
    }

    /**
     * Indicates the radio button has changed
     */
    public void stateChanged(final ChangeEvent e)
    {
      fireRadioChangeEvent();
    }

    /**
     * Indicates the text value changed
     */
    protected void handleChange(final DocumentEvent e)
    {
      fireValueChangeEvent();
    }
  }

  private class FileSelectAction extends AbstractAction
  {
    private FileSelectAction()
    {
      putValue(Action.NAME, "..");
    }

    public void actionPerformed(final ActionEvent aEvt)
    {
      final File reportContextFile = DesignTimeUtil.getContextAsFile(reportRenderContext.getReportDefinition());

      final FileFilter[] filters = {
          new FilesystemFilter(".properties", // NON-NLS
              Messages.getString("BundledResourceEditor.PropertiesTranslations")),
          new FilesystemFilter(new String[]{".xml", ".report", ".prpt", ".prpti", ".prptstyle"}, // NON-NLS
              Messages.getString("BundledResourceEditor.Resources"), true),
          new FilesystemFilter(new String[]{".gif", ".jpg", ".jpeg", ".png", ".svg", ".wmf"}, // NON-NLS
              Messages.getString("BundledResourceEditor.Images"), true),
      };

      final CommonFileChooser fileChooser = FileChooserService.getInstance().getFileChooser("resources");//NON-NLS
      fileChooser.setFilters(filters);

      final String sourceFile = sourceTextField.getText();
      if (StringUtils.isEmpty(sourceFile) == false)
      {
        if (reportContextFile != null)
        {
          fileChooser.setSelectedFile(new File(reportContextFile.getParentFile(), sourceTextField.getText()));
        }
        else
        {
          fileChooser.setSelectedFile(new File(sourceTextField.getText()));
        }
      }

      if (fileChooser.showDialog(ResourcePropertyEditorComponent.this, JFileChooser.OPEN_DIALOG) == false)
      {
        return;
      }
     
      final File file = fileChooser.getSelectedFile();
      if (file == null)
      {
        return;
      }

      final String path;
      if (reportContextFile != null)
      {
        path = IOUtils.getInstance().createRelativePath(file.getPath(), reportContextFile.getAbsolutePath());
      }
      else
      {
        path = file.getPath();
      }

      sourceTextField.setText(path);
    }
  }
}
TOP

Related Classes of org.pentaho.reporting.designer.core.util.table.ResourcePropertyEditorComponent

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.