/*!
* 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.editor.groups;
import org.pentaho.reporting.designer.core.Messages;
import org.pentaho.reporting.designer.core.editor.ReportDataChangeListener;
import org.pentaho.reporting.designer.core.editor.ReportDocumentContext;
import org.pentaho.reporting.designer.core.util.IconLoader;
import org.pentaho.reporting.designer.core.util.exceptions.UncaughtExceptionsModel;
import org.pentaho.reporting.designer.core.util.undo.EditGroupUndoEntry;
import org.pentaho.reporting.engine.classic.core.RelationalGroup;
import org.pentaho.reporting.libraries.base.util.CSVQuoter;
import org.pentaho.reporting.libraries.base.util.CSVTokenizer;
import org.pentaho.reporting.libraries.designtime.swing.BorderlessButton;
import org.pentaho.reporting.libraries.designtime.swing.CommonDialog;
import org.pentaho.reporting.libraries.designtime.swing.bulk.DefaultBulkListModel;
import org.pentaho.reporting.libraries.designtime.swing.bulk.RemoveBulkAction;
import org.pentaho.reporting.libraries.designtime.swing.bulk.SortBulkDownAction;
import org.pentaho.reporting.libraries.designtime.swing.bulk.SortBulkUpAction;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
public class EditGroupDetailsDialog extends CommonDialog implements ReportDataChangeListener {
private class AddSelectionAction extends AbstractAction implements ListSelectionListener {
private ListSelectionModel selectionModel;
/**
* Defines an <code>Action</code> object with a default description string and default icon.
*/
private AddSelectionAction( final ListSelectionModel selectionModel ) {
this.selectionModel = selectionModel;
putValue( Action.SMALL_ICON, IconLoader.getInstance().getFowardArrowIcon() );
putValue( Action.SHORT_DESCRIPTION, Messages.getString( "EditGroupDetailsDialog.AddColumn" ) );
selectionModel.addListSelectionListener( this );
setEnabled( selectionModel.isSelectionEmpty() == false );
}
public void valueChanged( final ListSelectionEvent e ) {
setEnabled( selectionModel.isSelectionEmpty() == false );
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed( final ActionEvent e ) {
final DefaultListModel data = getGroupFieldsModel();
final DefaultListModel fields = getAvailableFieldsModel();
for ( int i = 0; i < fields.getSize(); i++ ) {
if ( selectionModel.isSelectedIndex( i ) ) {
data.addElement( fields.getElementAt( i ) );
}
}
}
}
private class DoubleClickHandler extends MouseAdapter {
private ListSelectionModel selectionModel;
private DoubleClickHandler( final ListSelectionModel selectionModel ) {
this.selectionModel = selectionModel;
}
public void mouseClicked( final MouseEvent e ) {
if ( e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2 ) {
final DefaultListModel data = getGroupFieldsModel();
final DefaultListModel fields = getAvailableFieldsModel();
for ( int i = 0; i < fields.getSize(); i++ ) {
if ( selectionModel.isSelectedIndex( i ) ) {
data.addElement( fields.getElementAt( i ) );
}
}
}
}
}
private class ListTransferHandler extends TransferHandler {
private JList targetList;
private DefaultBulkListModel listModel;
private ListTransferHandler( final JList targetList,
final DefaultBulkListModel listModel ) {
this.targetList = targetList;
this.listModel = listModel;
}
public boolean importData( final TransferSupport support ) {
if ( support.isDataFlavorSupported( DataFlavor.stringFlavor ) == false ) {
return false;
}
if ( support.isDrop() == false ) {
return false;
}
try {
final String transferData = (String) support.getTransferable().getTransferData( DataFlavor.stringFlavor );
if ( transferData == null ) {
return false;
}
final CSVTokenizer tokenizer = new CSVTokenizer( transferData, ",", "\"" );
final ArrayList<String> items = new ArrayList<String>();
while ( tokenizer.hasMoreElements() ) {
items.add( tokenizer.nextToken() );
}
final DropLocation dropLocation = support.getDropLocation();
final Point point = dropLocation.getDropPoint();
final int idx = targetList.locationToIndex( point );
if ( idx == -1 ) {
for ( int i = 0; i < items.size(); i++ ) {
final String item = items.get( i );
listModel.addElement( item );
}
} else {
for ( int i = items.size() - 1; i >= 0; i -= 1 ) {
final String item = items.get( i );
listModel.add( idx, item );
}
}
} catch ( Exception e ) {
UncaughtExceptionsModel.getInstance().addException( e );
}
return super.importData( support );
}
public boolean canImport( final TransferSupport support ) {
if ( support.isDrop() == false ) {
return false;
}
return ( support.isDataFlavorSupported( DataFlavor.stringFlavor ) );
}
public int getSourceActions( final JComponent c ) {
return TransferHandler.COPY;
}
protected Transferable createTransferable( final JComponent c ) {
final JList lcomp = (JList) c;
final StringBuilder b = new StringBuilder();
final CSVQuoter quoter = new CSVQuoter( ',', '"' );
final Object[] selectedValues = lcomp.getSelectedValues();
for ( int i = 0; i < selectedValues.length; i++ ) {
if ( i != 0 ) {
b.append( ',' );
}
final Object value = selectedValues[ i ];
b.append( quoter.doQuoting( String.valueOf( value ) ) );
}
return new StringSelection( b.toString() );
}
}
private DefaultBulkListModel availableFieldsModel;
private DefaultBulkListModel groupFieldsModel;
private JTextField nameTextField;
private JList availableFields;
private JList groupFields;
public EditGroupDetailsDialog()
throws HeadlessException {
init();
}
public EditGroupDetailsDialog( final Frame owner )
throws HeadlessException {
super( owner );
init();
}
public EditGroupDetailsDialog( final Dialog owner )
throws HeadlessException {
super( owner );
init();
}
protected void init() {
setTitle( Messages.getString( "EditGroupDetailsDialog.Title" ) );
setModal( true );
availableFieldsModel = new DefaultBulkListModel();
groupFieldsModel = new DefaultBulkListModel();
nameTextField = new JTextField( 25 );
availableFields = new JList( availableFieldsModel );
availableFields.setDragEnabled( true );
availableFields.setTransferHandler( new ListTransferHandler( availableFields, availableFieldsModel ) );
availableFields.setDropMode( DropMode.ON );
availableFields.addMouseListener( new DoubleClickHandler( availableFields.getSelectionModel() ) );
groupFields = new JList( groupFieldsModel );
groupFields.setTransferHandler( new ListTransferHandler( groupFields, groupFieldsModel ) );
groupFields.setDragEnabled( true );
groupFields.setDropMode( DropMode.ON );
super.init();
}
protected String getDialogId() {
return "ReportDesigner.Core.EditGroupDetails";
}
protected Component createContentPane() {
final JPanel contentPane = new JPanel();
contentPane.setLayout( new BorderLayout() );
contentPane.add( createNamePanel(), BorderLayout.NORTH );
contentPane.add( createSelectionPane(), BorderLayout.CENTER );
return contentPane;
}
protected DefaultBulkListModel getAvailableFieldsModel() {
return availableFieldsModel;
}
protected DefaultBulkListModel getGroupFieldsModel() {
return groupFieldsModel;
}
public String getGroupName() {
if ( nameTextField.getText().length() == 0 ) {
return null;
}
return nameTextField.getText();
}
public void setGroupName( final String name ) {
this.nameTextField.setText( name );
}
public String[] getFields() {
final DefaultListModel data = this.getGroupFieldsModel();
final String[] fields = new String[ data.size() ];
for ( int i = 0; i < data.size(); i++ ) {
fields[ i ] = (String) data.get( i );
}
return fields;
}
public void setFields( final String[] groupFields ) {
final DefaultListModel data = getGroupFieldsModel();
data.clear();
for ( int i = 0; i < groupFields.length; i++ ) {
data.addElement( groupFields[ i ] );
}
}
public void dataModelChanged( final ReportDocumentContext context ) {
final String[] columnNames = context.getReportDataSchemaModel().getColumnNames();
final DefaultListModel availableFieldsModel = getAvailableFieldsModel();
availableFieldsModel.clear();
for ( int i = 0; i < columnNames.length; i++ ) {
availableFieldsModel.addElement( columnNames[ i ] );
}
}
public boolean editGroupData( final String name,
final String[] groupFields,
final ReportDocumentContext reportRenderContext ) {
if ( reportRenderContext == null ) {
throw new NullPointerException();
}
setGroupName( name );
setFields( groupFields );
try {
nameTextField.setText( name );
reportRenderContext.addReportDataChangeListener( this );
dataModelChanged( reportRenderContext );
if ( performEdit() == false ) {
return false;
}
return true;
} finally {
reportRenderContext.removeReportDataChangeListener( this );
}
}
public EditGroupUndoEntry editGroup( final RelationalGroup group,
final ReportDocumentContext reportRenderContext,
final boolean addGroup ) {
if ( addGroup ) {
setTitle( Messages.getString( "EditGroupDetailsDialog.AddTitle" ) );
} else {
setTitle( Messages.getString( "EditGroupDetailsDialog.Title" ) );
}
final String oldName = group.getName();
final String[] oldFields = group.getFieldsArray();
if ( editGroupData( oldName, oldFields, reportRenderContext ) ) {
return new EditGroupUndoEntry( group.getObjectID(), oldName, getGroupName(), oldFields, getFields() );
}
return null;
}
private JPanel createNamePanel() {
final JPanel theNamePanel = new JPanel( new FlowLayout( FlowLayout.LEFT, 5, 5 ) );
theNamePanel.setBorder( BorderFactory.createEmptyBorder( 5, 0, 5, 5 ) );
theNamePanel.add( new JLabel( Messages.getString( "EditGroupDetailsDialog.Name" ) ) );
theNamePanel.add( nameTextField );
return theNamePanel;
}
private JPanel createSelectionPane() {
final JButton columnsAdd = new BorderlessButton( new AddSelectionAction( availableFields.getSelectionModel() ) );
final JLabel columnsLabel = new JLabel( Messages.getString( "EditGroupDetailsDialog.SelectedItems" ) );
final ListSelectionModel columnsSelectionModel = groupFields.getSelectionModel();
final JButton columnsSortUp =
new BorderlessButton( new SortBulkUpAction( groupFieldsModel, columnsSelectionModel ) );
final JButton columnsSortDown =
new BorderlessButton( new SortBulkDownAction( groupFieldsModel, columnsSelectionModel ) );
final JButton columnsRemove =
new BorderlessButton( new RemoveBulkAction( groupFieldsModel, columnsSelectionModel ) );
final JPanel tablesPane = new JPanel();
tablesPane.setLayout( new GridBagLayout() );
final JLabel tablesColumnsLabel = new JLabel( Messages.getString( "EditGroupDetailsDialog.AvailableFields" ) );
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 2;
gbc.insets = new Insets( 5, 5, 5, 5 );
gbc.anchor = GridBagConstraints.WEST;
tablesPane.add( tablesColumnsLabel, gbc );
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 3;
gbc.weighty = 5;
gbc.gridheight = 1;
gbc.weightx = 2;
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets( 0, 5, 5, 5 );
final JScrollPane comp = new JScrollPane
( availableFields, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED );
tablesPane.add( comp, gbc );
gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx = 2;
gbc.gridy = 2;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets( 5, 5, 5, 5 );
tablesPane.add( columnsLabel, gbc );
gbc = new GridBagConstraints();
gbc.gridx = 3;
gbc.gridy = 2;
gbc.insets = new Insets( 5, 5, 5, 5 );
tablesPane.add( columnsSortUp, gbc );
gbc = new GridBagConstraints();
gbc.gridx = 4;
gbc.gridy = 2;
gbc.insets = new Insets( 5, 5, 5, 5 );
tablesPane.add( columnsSortDown, gbc );
gbc = new GridBagConstraints();
gbc.gridx = 5;
gbc.gridy = 2;
gbc.insets = new Insets( 5, 5, 5, 5 );
tablesPane.add( columnsRemove, gbc );
gbc = new GridBagConstraints();
gbc.gridx = 2;
gbc.gridy = 3;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridwidth = 4;
gbc.insets = new Insets( 0, 5, 5, 0 );
tablesPane.add( new JScrollPane
( groupFields, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED ), gbc );
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 3;
gbc.insets = new Insets( 5, 5, 5, 0 );
tablesPane.add( columnsAdd, gbc );
return tablesPane;
}
}